我们说我有NotificationManager
这个函数:
func receivedRemoteNotification(userInfo: [NSObject: AnyObject], fetchCompletionHandler: UIBackgroundFetchResult -> Void) {
guard isValidPayload(userInfo) else {
fetchCompletionHandler(.Failed)
return
}
doSomethingAsyncWithCompletionHandler(fetchCompletionHandler)
}
有没有办法告诉编译器,无论代码路径是什么,fetchCompletionHandler
必须总是?
答案 0 :(得分:2)
您可以使用defer
块指定在当前函数结束之前要执行的代码。
func foo() {
defer {
print("This will always be printed before the end")
}
print("Some code")
}
foo()
> Some code
> This will always be printed before the end
所以你可以这样更新你的功能
func receivedRemoteNotification(userInfo: [NSObject: AnyObject], fetchCompletionHandler: UIBackgroundFetchResult -> Void) {
defer {
// call fetchCompletionHandler here
}
guard isValidPayload(userInfo) else {
fetchCompletionHandler(.Failed)
return
}
fetchCompletionHandler(.NewData)
}
当然要注意避免多次通话。
Swift有一种机制可以发现代码的每个可能的分支在使用之前都会初始化一个常量。
您可以利用此技术声明必须初始化的常量
let result: UIBackgroundFetchResult
并添加defer
块,其中fetchCompletionHandler
与前一个常量一起调用。
defer {
fetchCompletionHandler(result)
}
现在编译器将强制您在当前函数结束之前在每个可能的分支中填充result
。
func receivedRemoteNotification(userInfo: [NSObject: AnyObject], fetchCompletionHandler: UIBackgroundFetchResult -> ()) {
let result: UIBackgroundFetchResult
defer {
fetchCompletionHandler(result)
}
guard isValidPayload(userInfo) else {
result = .Failed // if you remove this you get a compiler error
return
}
result = .NewData // if you remove this you get a compiler error
}