Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift 2 Error Handling in Practice

58b40ae3b0db6cf0202a3802e9dd70fe?s=47 cockscomb
August 30, 2015

Swift 2 Error Handling in Practice

Presented @ Swift 2 Symposium #2

58b40ae3b0db6cf0202a3802e9dd70fe?s=128

cockscomb

August 30, 2015
Tweet

Transcript

  1. Swift 2
 Error Handling in Practice

  2. cockscomb

  3. None
  4. Recent work • Rewrite Hatena Blog for iOS with Swift

    • Hatena Summer Internship 2015 “iOS App Course” • Sample code: hatena/swift-Sample-GitHubSearch • Textbook: Available soon • Secret projects‥
  5. I moved our codes 
 into Swift 2 the past

    week
  6. Swift 2
 Error Handling in Practice

  7. Which is better? func parseInt(string: String) -> Int? func parseInt(string:

    String) throws -> Int func parseInt(string: String) throws -> Int?
  8. Which is better? func parseInt(string: String) -> Int?

  9. Which is better? func parseJSON(data: NSData) -> JSONObject? func parseJSON(data:

    NSData) throws -> JSONObject func parseJSON(data: NSData) throws -> JSONObject?
  10. Which is better? func parseJSON(data: NSData) throws -> JSONObject

  11. func parseJSON(data: NSData) throws -> JSONObject do { let json

    = try parseJSON(data) // Something } catch { // Handle error } if let json = try? parseJSON(data) { // Something }
  12. enum JSONDecodeError: ErrorType { case MissingRequiredKey(String) case UnexpectedType(key: String, expected:

    Any.Type, actual: Any.Type) } struct JSONObject { let raw: [String : AnyObject] func getValue<T>(key: String) throws -> T { guard let value = raw[key] else { throw JSONDecodeError.MissingRequiredKey(key) } guard let typedValue = value as? T else { throw JSONDecodeError.UnexpectedType( key: key, expected: T.self, actual: value.dynamicType) } return typedValue } }
  13. do { let json = try parseJSON(data) let userName: String

    = try json.getValue("user_name") // Something } catch { // Handle error } if let json = try? parseJSON(data), let userName: String = try? json.getValue("user_name") { // Something }
  14. Which is better? enum JSONDecodeError: ErrorType { case MissingRequiredKey(String) case

    UnexpectedType(key: String, expected: Any.Type, actual: Any.Type) } enum JSONDecodeError: ErrorType { case MissingRequiredKey case UnexpectedType }
  15. Which is better? enum JSONDecodeError: ErrorType { case MissingRequiredKey(String) case

    UnexpectedType(key: String, expected: Any.Type, actual: Any.Type) }
  16. Do more better enum JSONDecodeError: ErrorType, CustomDebugStringConvertible { case MissingRequiredKey(String)

    case UnexpectedType(key: String, expected: Any.Type, actual: Any.Type) var debugDescription: String { switch self { case .MissingRequiredKey(let key): return "Required key '\(key)' missing" case let .UnexpectedType(key: key, expected: expected, actual: actual): return "Unexpected type '\(actual)' was supplied for '\(key): \(expected)'" } } }
  17. Do more better struct JSONObject { let raw: [NSString :

    AnyObject] /** Get typed value for the key - parameters: - key: JSON key - returns: Typed value */ func getValue<T>(key: String) throws -> T { guard let value = raw[key] else { throw JSONDecodeError.MissingRequiredKey(key) } ...
  18. Do more better struct JSONObject { let raw: [NSString :

    AnyObject] /** Get typed value for the key - parameters: - key: JSON key - returns: Typed value - throws: JSONDecodeError */ func getValue<T>(key: String) throws -> T { guard let value = raw[key] else { throw JSONDecodeError.MissingRequiredKey(key) } ...
  19. as NSError enum MyError: ErrorType { case SuperError } let

    error = MyError.SuperError as NSError print(error.localizedDescription) // The operation couldn’t be completed.
 (Module.MyError error 0.)
  20. enum MyError: ErrorType { case SuperError static func description(code: Int)

    -> String? { switch code { case 0: return "Super error occurred" default: return nil } } } NSError.setUserInfoValueProviderForDomain("Module.MyError") { (error, userInfoKey) -> AnyObject? in switch userInfoKey { case NSLocalizedDescriptionKey: return MyError.description(error.code) default: break } return nil } let error = MyError.SuperError as NSError print(error.localizedDescription) // Super error occurred
  21. Error handling in practice • Functions can return Optional type

    or throw error • ErrorType should provide informations in detail • Documentation comment with possible error kind • Treating ErrorType as NSError have some problems