Error Handling in Swift

28

Transcript of Error Handling in Swift

Page 1: Error Handling in Swift
Page 2: Error Handling in Swift

ERROR HANDLING IN COCOA

Page 3: Error Handling in Swift

AGENDA

Objective-C’s NSError

Swift’s try/catch/throws

Swift’s Result<S,F> type

Exceptions & Assertions

Page 4: Error Handling in Swift

OBJECTIVE-C ERROR HANDLING

Page 5: Error Handling in Swift

NSERROR IN OBJECTIVE-C NSError *error = nil; NSString *string = [NSString stringWithContentsOfFile:@"test.txt" encoding:NSUTF8StringEncoding error:&error]; if (!string) { NSLog(@"File could not be read!"); } if (error) { NSLog(@"%@", error.localizedDescription); }

Page 6: Error Handling in Swift

NSERROR IN OBJECTIVE-C

Return value is most relevant for checking whether an operation was successful or not [1]

Methods can return errors, but still successfully return a value

[1] Apple Error Handling Documentation

Page 7: Error Handling in Swift

NSERROR IN OBJECTIVE-C… …IN THE SAD REAL WORLD

NSString *string = [NSString stringWithContentsOfFile:@"test.txt" encoding:NSUTF8StringEncoding error:nil];

Page 8: Error Handling in Swift

SWIFT ERROR HANDLING

Page 9: Error Handling in Swift

SWIFT ERROR HANDLING

Swift 2 uses throws instead of NSError

Objective-C methods are bridged to Swift accordingly:

Page 10: Error Handling in Swift

CALLING THROWING FUNCTIONS

You need to choose one of these 3 approaches:

handle the error with a do/catch block

Use forced-try: try!

propagate the error further up the call stack by

declaring calling function as throws

Page 11: Error Handling in Swift

DO/CATCH IN SWIFT

do { let content = try String(contentsOfFile: “test.txt", encoding: NSUTF8StringEncoding) } catch let error as NSError { print(error) }

Page 12: Error Handling in Swift

DECLARING ERROR TYPES

How do you know which types of errors to catch?

Header documentation!

Unfortunately throws has no type information

Page 13: Error Handling in Swift

DECLARING ERROR TYPES/** - Returns: the content of the file - Throws: `NSError` if file could not be read*/func readFile() throws -> String { //...}

Page 14: Error Handling in Swift

DEFINING SWIFT ERROR TYPES

enum FileReadError: ErrorType { case InvalidFilePath case InvalidEncoding case IncorrectFileFormat(actualFileFormat: String)}

Page 15: Error Handling in Swift

THROWING SWIFT ERROR TYPES

/**- Returns: The content of the file- Throws: `FileReadError.InvalidFilePath` if file could not be read; `FileReadError.InvalidEncoding` if file encoding does not match expected encoding; `FileReadError.IncorrectFileFormat` if file format does not match specified one*/func readFile(path: String) throws -> NSData { // ... throw FileReadError.InvalidFilePath}

Page 16: Error Handling in Swift

HANDLING SWIFT ERROR TYPES

do { try readFile("test.txt") } catch FileReadError.InvalidFilePath { print("Invalid filepath") } catch FileReadError.InvalidEncoding { print("Invalid encoding") } catch let FileReadError.IncorrectFileFormat(actualFileFormat) { print("Unexpected file format: \(actualFileFormat)") } catch { print("Unhandled Error!") }

Page 17: Error Handling in Swift

LIMITATIONS OF SWIFT ERROR HANDLING

Errors don’t have type information

Error handling doesn’t work for asynchronous code

let request = NSURLRequest(URL: NSURL(string: "https://www.google.com")!) let session = NSURLSession.sharedSession() session.dataTaskWithRequest(request) { (data, response, error) -> Void in // error handling happens in callback }

Page 18: Error Handling in Swift

RESULT TYPE

Result type can represent value or error depending on

result of operation. Popular Open Source

implementation: [2]

Can be used for synchronous and asynchronous code

func search(searchString: String) -> Result<Predictions, SearchError>

[2] https://github.com/antitypical/Result

Page 19: Error Handling in Swift

CONSUMING RESULT TYPE

func handleSearchResult(result: Result<Predictions, Reason>) -> Void { switch result { case let .Success(predictions): self.locations = predictions.predictions case .Failure(_): self.errorHandler.displayErrorMessage( "The search returned an error, sorry!" ) } }

Page 20: Error Handling in Swift

PRODUCING RESULT TYPE

func fetchAllTrips(callback: Result<[JSONTrip], Reason> -> Void) { // in case of success var trips: [JSONTrip] = [/*...*/] callback(.Success(trips)) // in case of error var reason: Reason = .NoData callback(.Failure(reason)) }

Page 21: Error Handling in Swift

ASSERTIONS AND EXCEPTIONS

Page 22: Error Handling in Swift

EXCEPTIONS

Objective-C provides exceptions, Swift does not

Objective-C exceptions should not be caught, they are

not intended for error handling [1]

Exceptions are used to crash the app to make you

aware of a programming error

[1] Apple Error Handling Documentation

Page 23: Error Handling in Swift

ASSERTIONS

Are used to state and verify assumptions

Typically only used at debug time

Objective-C: NSAssert…

Swift: assert, assertionFailure, fatalError,… [3]

[3] Swift asserts the missing manual

Page 24: Error Handling in Swift

ASSERTIONS

Page 25: Error Handling in Swift

SUMMARY

Page 26: Error Handling in Swift

SUMMARYSwift 2 uses ErrorType and throws for error

handling

Swift 2 error handling has limitations (no type info,

not suitable for async code) - Result type is a

good alternative

Exceptions and assertions are used for

unrecoverable errors

Page 27: Error Handling in Swift

ADDITIONAL RESOURCES

Page 28: Error Handling in Swift

ADDITIONAL RESOURCES

WWDC 106: What’s new in Swift

Javi Soto: Swift Sync and Async Error Handling

Benjamin Encz: Swift Error Handling and Objective-C Interop in Depth