Share
Embed
Transcript
39 slides
-
૪ ࠴ ࡻ ࡨ ࡥ ࢊ ࠴
ࡪ ࢫ ߭ -
• Error Handling Basics • guard, defer • Closure •
Asynchronous callback • Exhaustive -
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 -
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 -
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 -
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 -
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 -
Error Handling Basics • Before Swift 2, NSErrorPointer • ErrorType
• throw, try, catch • Propagation -
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 -
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 -
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 -
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 -
enum MyError: ErrorType { case DangerousError } func execute(closure: ()
throws -> Void) rethrows { try closure() } execute({ print("No error") }) Assumed no error -
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 -
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 -
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 -
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 -
Asynchronous callback • Optional, Optional • f: () throws ->
Result • ValueOrError value -
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 -
–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.” -
enum MyError: ErrorType { case DangerousError } func doSomething() throws
{ throw MyError.DangerousError } func test() { do { try doSomething() } catch MyError.DangerousError { print("Error") } } -
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 -
Errors thrown from here are not handled because the enclosing
catch is not exhaustive. ! -
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 -
• Error Handling Basics • guard, defer • Closure •
Asynchronous callback • Exhaustive -
૪ ࠴ ࡻ ࡨ ࡥ ࢊ ࠴
ࡪ ࢫ ߭