这个完成处理程序究竟是如何工作的?

How exactly does this completion handler work?

我已经对闭包、接收参数的闭包、尾随闭包和完成处理程序进行了一些研究,但我很难理解何时传递完成的两个参数、管理器和文件。在 pick() 函数定义中,函数范围内没有任何地方使用 completion(manager, file) 语法调用完成。然而,有一个 present 方法,我想我遗漏了一些关于 present() 的东西,它可能包括用适当的参数调用完成闭包。非常感谢您的帮助。

public func pick(from vc: UIViewController?, withCompletion completion: @escaping (_ manager: HSDriveManager?, _ file: GTLRDrive_File?) -> Void) {
        viewer?.completion = completion
        viewer?.shouldSignInOnAppear = true
        
        //As of now, present() seems to include the calling of the completion closure.
        //self is the HSDriverPicker class
        print(type(of: self))
        vc?.present(self, animated: true)
        
    }

下面的代码是pick的函数调用。让我感到困惑的是,为了让管理器和文件在函数调用的某处像完成闭包的参数一样工作,有一个部分传递了这些参数。我没有看到他们。如果您对当前方法的具体作用以及它是否负责调用包含必要参数的闭包有深入的了解,我将不胜感激。

picker.pick(from: self) {
                (manager, file) in

                print("picked file: \(file?.name ?? "-none-")")

                let destinationPath = "/Users/james/Desktop/tests"
                
                manager!.downloadFile(file!, toPath: destinationPath, withCompletionHandler: {
                    error in

                    if error != nil {
                        print("Error downloading : \(error?.localizedDescription ?? "")")
                    }
                    else {
                        print("Success downloading to : \(destinationPath)")
                    }
                })
            }

函数present(_:animated:) 不负责调用完成闭包。 viewer?.completion = completion 意味着 viewer 将负责在其范围内调用完成闭包(这就是为什么使用 @escaping 的原因,即闭包将比您传递给它的范围长)。 managerfile 这两个参数不应该由客户端传递,而是暴露给客户端,以便调用 picker.pick 的任何人都可以使用这些属性并执行特定的操作然后会在viewer里面调用。带参数的闭包仅仅意味着客户端可以使用该参数而不必担心这些参数将传递给谁以及何时传递。