在调用完成处理程序或 return 完成处理程序参数后返回?

Returning after calling completion handler, or return completion handler parameter?

我有一个方法可以总结成这样:

func apply(username: String, email: String, password: String,
           onDone: @escaping (_ error: Error?) -> ())
{
    //Do async stuff
    do
    {
        try asyncGood()
        onDone(nil)
        return
    }
    catch
    {
        onDone(error)
        return
    }
}

这样做有什么区别:

return onDone(error)

对比

onDone(error)
return

?
它只是节省了额外的一行代码吗?我看不出两者有什么区别。我是否遗漏了异步 Swift 编程的一些基本方面?

在您看来,我是否应该始终尝试压缩所有内容,以便 onDone(...) 最后只被调用 一次

在语义上,这两种情况是相同的。你基本上是在说:

return ()

你的方法声明为 return (),并且由于 onDone 闭包也 return 是 (),你可以说 return onDone(error). return 类型匹配。

但是,我发现将它们写在 2 个单独的行中更具可读性:

// This clearly shows that you are doing 2 separate things
onDone(error) // call the completion handler
return // return

甚至省略 return!

onDone(error)
// there will be an implicit return at the end of the method.

两者相同。 apply函数return类型是Void并且onDone闭包return类型也是Void。所以两者是一样的。

return onDone(error)

onDone(error)
return

或者您可以忽略 return 因为 return 类型是 Void

onDone(error)

没有区别。事实上,根本不需要 return 关键字。

对于 swift 以下所有声明都是等效的:

func doNothing() {
}

func doNothing2() -> Void {
}

func doNothing3() -> () {
}

func doNothing4() {
    return ()
}

func doNothing5() -> Void {
    return ()
}

当你return()你return什么都没有。无 return 与 return 无完全相同。函数 returning Void 可以等效地用作以下

doNothing()

var result = doNothing()

此外,Void还可以作为类型参数,这是一个非常强大的特性:

func genericCall<T>(_ f: () -> T) -> T {
    return f()
}

var result1 = genericCall { print("test") } // result1 is Void
var result2 = genericCall { return 5 } // result2 is Int

回答你最初的问题,我建议完全省略 return

func doStuffAsync(_ callback: @escaping (Error?) -> Void) {
    // Just an example. Could be any other async call.
    DispatchQueue.main.async {
        do {
            try doStuff()
            callback(nil)
        }
        catch {
            callback(error)
        }
    }
}