sha*_*oga 20 throws ios swift2
我有一个抛出错误的函数,在这个函数中我有一个inside a闭包,我需要从它的完成处理程序抛出错误.那可能吗 ?
到目前为止,这是我的代码.
enum CalendarEventError: ErrorType {
case UnAuthorized
case AccessDenied
case Failed
}
func insertEventToDefaultCalendar(event :EKEvent) throws {
let eventStore = EKEventStore()
switch EKEventStore.authorizationStatusForEntityType(.Event) {
case .Authorized:
do {
try insertEvent(eventStore, event: event)
} catch {
throw CalendarEventError.Failed
}
case .Denied:
throw CalendarEventError.AccessDenied
case .NotDetermined:
eventStore.requestAccessToEntityType(EKEntityType.Event, completion: { (granted, error) -> Void in
if granted {
//insertEvent(eventStore)
} else {
//throw CalendarEventError.AccessDenied
}
})
default:
}
}
Run Code Online (Sandbox Code Playgroud)
mix*_*xel 16
定义抛出的闭包时:
enum MyError: ErrorType {
case Failed
}
let closure = {
throw MyError.Failed
}
Run Code Online (Sandbox Code Playgroud)
那么这个闭包的类型是() throws -> ()和作为参数获取此闭包的函数必须具有相同的参数类型:
func myFunction(completion: () throws -> ()) {
}
Run Code Online (Sandbox Code Playgroud)
这个函数可以调用completion闭包同步:
func myFunction(completion: () throws -> ()) throws {
completion()
}
Run Code Online (Sandbox Code Playgroud)
并且你必须添加throws关键字到函数签名或调用完成try!:
func myFunction(completion: () throws -> ()) {
try! completion()
}
Run Code Online (Sandbox Code Playgroud)
或异步:
func myFunction(completion: () throws -> ()) {
dispatch_async(dispatch_get_main_queue(), { try! completion() })
}
Run Code Online (Sandbox Code Playgroud)
在最后一种情况下,您将无法捕获错误.
因此,如果方法中的completion闭包eventStore.requestAccessToEntityType和方法本身没有throws签名或者completion是异步调用那么你就不throw能从这个闭包中获取.
我建议您使用以下函数实现将错误传递给回调而不是抛出它:
func insertEventToDefaultCalendar(event: EKEvent, completion: CalendarEventError? -> ()) {
let eventStore = EKEventStore()
switch EKEventStore.authorizationStatusForEntityType(.Event) {
case .Authorized:
do {
try insertEvent(eventStore, event: event)
} catch {
completion(CalendarEventError.Failed)
}
case .Denied:
completion(CalendarEventError.AccessDenied)
case .NotDetermined:
eventStore.requestAccessToEntityType(EKEntityType.Event, completion: { (granted, error) -> Void in
if granted {
//insertEvent(eventStore)
} else {
completion(CalendarEventError.AccessDenied)
}
})
default:
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,这是不可能的 - 完成处理程序必须用throws(和方法rethrows)声明,而这个不是.
请注意,所有抛出只是NSError **Objective-C(inout error参数)中的不同符号.Objective-C回调没有inout参数,因此无法传递错误.
您将不得不使用不同的方法来处理错误.
通常,NSError **在Obj-C或throwsSwift中,异步方法不能很好地兼容,因为错误处理可以同步工作.
因为throw是同步的,所以想要抛出的异步函数必须有一个抛出的内部闭包,例如:
func insertEventToDefaultCalendar(event :EKEvent, completion: (() throws -> Void) -> Void) {
let eventStore = EKEventStore()
switch EKEventStore.authorizationStatusForEntityType(.Event) {
case .Authorized:
do {
try insertEvent(eventStore, event: event)
completion { /*Success*/ }
} catch {
completion { throw CalendarEventError.Failed }
}
case .Denied:
completion { throw CalendarEventError.AccessDenied }
case .NotDetermined:
eventStore.requestAccessToEntityType(EKEntityType.Event, completion: { (granted, error) -> Void in
if granted {
let _ = try? self.insertEvent(eventStore, event: event)
completion { /*Success*/ }
} else {
completion { throw CalendarEventError.AccessDenied }
}
})
default:
break
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在呼叫站点,您可以像这样使用它:
insertEventToDefaultCalendar(EKEvent()) { response in
do {
try response()
// Success
}
catch {
// Error
print(error)
}
}
Run Code Online (Sandbox Code Playgroud)