确保在* all *代码路径中使用参数的方法?

时间:2015-12-08 20:18:21

标签: swift

我们说我有NotificationManager这个函数:

func receivedRemoteNotification(userInfo: [NSObject: AnyObject], fetchCompletionHandler: UIBackgroundFetchResult -> Void) {
    guard isValidPayload(userInfo) else {
        fetchCompletionHandler(.Failed)
        return
    }

    doSomethingAsyncWithCompletionHandler(fetchCompletionHandler)
}

有没有办法告诉编译器,无论代码路径是什么,fetchCompletionHandler必须总是

1 个答案:

答案 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
}