完成处理程序是否结束该函数?

Zba*_*itZ 1 completionhandler swift

也许我不理解完成处理程序的概念,但我有一个像这样的函数;

func someFunction(completion: @escaping (Bool, LoginError?) -> Void) {
    self.checkDevice() { allowed, error in
       if let e = error {
          completion(false, e)
       }
        completion(true, nil)
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然不了解具体内容checkDevice(),但基本前提是它执行异步网络调用,并返回true且无错误 (nil),或者返回false(有错误)。

当我运行此代码时,我发现完成处理程序被调用两次。它将完成作为元组 (as false, error) 和 ( true, nil) 发送。我已经做了一些调试,似乎没有办法someFunction()调用两次。

我相信一旦发送完成,函数就会结束。在我的测试用例中,我强制从 中产生错误checkDevice(),这应该会导致我将完成发送为 ( false, error),但我同时看到 ( false, error) 和 ( true, nil)。完成不会立即结束函数吗?

mat*_*att 5

\n

我相信一旦发送完成,函数就会结束。

\n
\n\n

不,为什么会这样?当您调用此函数时,它就像调用任何其他函数一样。这个名字没有魔力。

\n\n

像这样重写它:

\n\n
func someFunction(completion: @escaping (Bool, LoginError?) -> Void) {\n    self.checkDevice() { allowed, error in\n        if let e = error {\n            completion(false, e)\n            return // *\n        }\n        completion(true, nil)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

实际上,我应该指出,这是编写完成处理程序的糟糕方法。它不应该采用两个参数,一个 Bool 和一个仅在 Bool 为 时才使用的可选 LoginError false,而应该采用一个参数 \xe2\x80\x94 一个 Result,它携带我们是否成功或失败,以及如果我们失败了,什么错误是:

\n\n
func someFunction(completion: @escaping (Result<Void, Error>) -> Void) {\n    self.checkDevice() { allowed, error in\n        completion( Result {\n            if let e = error { throw e }\n        })\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

正如您所看到的,使用结果作为参数可以让您更优雅地响应发生的情况。

\n\n

事实上,checkDevice它本身可以将 Result 传递到完成处理程序中,然后事情会更加优雅(也更简单)。

\n