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

Me and Swift and error

Me and Swift and error

Presented at “Swift 2 (& LLDB) Symposium”

cockscomb

July 03, 2015
Tweet

More Decks by cockscomb

Other Decks in Programming

Transcript

  1. • Error Handling Basics • guard, defer • Closure •

    Asynchronous callback • Exhaustive
  2. enum MyError: Int { static let domain = "MyErrorDomain" case

    DangerousError = -999 } func awesome(error: NSErrorPointer) -> String? { error.memory = NSError(domain: MyError.domain, code: MyError.DangerousError.rawValue, userInfo: nil) return nil } func test() { var error: NSError? let result = awesome(&error) if let r = result { print(r) } if let e = error { print(e) } } test() Swift 1.x
  3. enum MyError: ErrorType { case DangerousError } func awesome() throws

    -> String { if fail { throw MyError.DangerousError } return "awesome" } func test() { do { let result = try awesome() print(result) } catch { print("Error") } } test() Using ErrorType
  4. enum MyError: ErrorType { case DangerousError(String) } func awesome() throws

    -> String { if fail { throw MyError.DangerousError("Too dangerous") } return "awesome" } func test() { do { let result = try awesome() print(result) } catch MyError.DangerousError(let message) { print(message) } catch { print("Error") } } test() Error information
  5. enum MyError: ErrorType { case DangerousError } func awesome() throws

    -> String { if fail { throw MyError.DangerousError } return "awesome" } func test() throws { let result = try awesome() print(result) } do { try test() } catch { print("Error") } Propagate error
  6. enum MyError: ErrorType { case DangerousError } func awesome() throws

    -> String { if fail { throw MyError.DangerousError } return "awesome" } func test() { let result = try! awesome() print(result) } test() Forced-try
  7. struct Dog { enum Error: ErrorType { case Sleeping }

    enum State { case Sitting case Sleeping case Walking } var state: State = .Sitting mutating func walk() throws { guard state != .Sleeping else { throw Error.Sleeping } state = .Walking } } guard
  8. struct Human { enum State { case Standing case Walking

    } var state: State = .Standing mutating func walk(inout dog: Dog) throws { defer { dog.praise() } try dog.walk() state = .Walking } } defer
  9. enum MyError: ErrorType { case DangerousError } func execute(closure: ()

    throws -> Void) throws { try closure() } do { try execute({ throw MyError.DangerousError }) } catch { print("Error") } Closures can throw
  10. enum MyError: ErrorType { case DangerousError } func execute(closure: ()

    throws -> Void) throws { try closure() } do { try execute({ print("No error") }) } catch { print("Error") } Assumed no error but catch
  11. enum MyError: ErrorType { case DangerousError } func execute(closure: ()

    throws -> Void) rethrows { try closure() } execute({ print("No error") }) Assumed no error
  12. enum MyError: ErrorType { case DangerousError } func doAsync(callback: (result:

    String?, error: ErrorType?) -> Void) { dispatch_async(dispatch_get_main_queue()) { callback(result: nil, error: MyError.DangerousError) } } doAsync { (result, error) in if let result = result { print(result) } else if let error = error { print("Error") } } Asynchronous callback
  13. enum MyError: ErrorType { case DangerousError } func doAsync(callback: (()

    throws -> String) -> Void) { dispatch_async(dispatch_get_main_queue()) { callback({ throw MyError.DangerousError }) } } doAsync { (f) in do { let result = try f() } catch { print("Error") } } Asynchronous callback
  14. enum ValueOrError<T> { case Value(T) case Error(ErrorType) init(_ value: T)

    { self = Value(value) } init(_ error: ErrorType) { self = Error(error) } func get() throws -> T { switch self { case .Value(let value): return value case .Error(let error): throw error } } } Value or Error
  15. enum MyError: ErrorType { case DangerousError } func doAsync(callback: (ValueOrError<String>)

    -> Void) { dispatch_async(dispatch_get_main_queue()) { callback(ValueOrError(MyError.DangerousError)) } } doAsync { (v) in do { let result = try v.get() } catch { print("Error") } } Asynchronous callback
  16. func doAsync(callback : String catches -> Void) { if (success)

    { callback("hooray!") } else { callback(throw MyError.Failed) } } doAsync { result in // handle result } catch { // Catch async thrown error } Suggested in developer forums https://forums.developer.apple.com/thread/4354 Unreal
  17. –The Swift Programming Language “Like a switch statement, the compiler

    attempts to infer whether catch clauses are exhaustive. If such a determination can be made, the error is considered handled.”
  18. enum MyError: ErrorType { case DangerousError } func doSomething() throws

    { throw MyError.DangerousError } func test() { do { try doSomething() } catch MyError.DangerousError { print("Error") } }
  19. Errors thrown from here are not handled b ! enum

    MyError: ErrorType { case DangerousError } func doSomething() throws { throw MyError.DangerousError } func test() { do { try doSomething() } catch MyError.DangerousError { print("Error") } } Not exhaustive
  20. Errors thrown from here are not handled b ! enum

    MyError: ErrorType { case DangerousError } func doSomething() throws { throw MyError.DangerousError } func test() { do { try doSomething() } catch MyError.DangerousError { print("Error") } } Not exhaustive
  21. • Error Handling Basics • guard, defer • Closure •

    Asynchronous callback • Exhaustive