在Cocoa中,执行异步操作的方法将完成处理程序作为其最后一个参数,该方法在操作完成后调用该块以返回结果或错误。Swift 5.5及更高版本使用Swift的本地并发支持,除了将基于回调的方法版本导入Swift之外,还自动将使用完成处理程序的Objective-C方法转换为异步方法。因为两个Swift方法具有相同的行为,所以它们在文档中共享相同的页面。
有关异步函数的信息,请参阅Swift编程语言中的并发。
Swift将接受完成处理程序的Objective-C方法导入为两个相关的Swift方法:一个接受闭包的方法和一个不接受闭包的异步方法。例如,考虑PassKit中的present(completion:)方法。在Objective-C中,它是这样声明的:
- (void)presentWithCompletion:(void (^)(BOOL success))completion;
然而,在Swift中,它被导入为两种方法:
func present(completion: ((Bool) -> Void)? = nil)
func present() async -> Bool
第一个版本present(completion:)的返回类型为Void,并采用一个完成处理程序。第二个版本present()返回一个布尔值,是一个异步方法。
完成处理程序填充NSError指针参数的方法也会成为Swift中的抛出方法,如关于导入的Cocoa错误参数中所述。异步抛出方法上的NSError参数也必须可以为null,这表示该参数仅用于传递错误。例如,考虑URLSessionStreamTask中的write(_:timeout:completeHandler:)方法。在Objective-C中,它是这样声明的:
- (void)writeData:(NSData *)data
timeout:(NSTimeInterval)timeout
completionHandler:(void (^) (NSError * _Nullable error))completionHandler;
与前面的例子一样,Swift将这个Objective-C方法导入为两个方法:一个是采用闭包的异步方法,另一个是异步抛出方法。
func write(
_ data: Data,
timeout: TimeInterval,
completionHandler: @escaping (Error?) -> Void
)
func write(_ data: Data, timeout: TimeInterval) async throws
完成处理程序采用多个参数的方法将成为返回元组的方法。例如,PassKit中的sign(_:using:completion:)方法在Objective-C中声明如下:
- (void)signData:(NSData *)signData
withSecureElementPass:(PKSecureElementPass *)secureElementPass
completion:(void (^)(NSData *signedData, NSData *signature, NSError *error))completion;
在Swift中,它被导入为两个方法,一个是接受闭包的异步方法,另一个是返回元组的异步抛出方法:
func sign(
_ signData: Data,
using secureElementPass: PKSecureElementPass,
completion: @escaping (Data?, Data?, Error?) -> Void
)
func sign(_ signData: Data,
using secureElementPass: PKSecureElementPass
) async throws -> (Data, Data)
采用完成处理程序的方法必须满足以下要求:
WithCompletion
WithCompletionHandler
WithCompletionBlock
WithReplyTo
WithReply
如果该方法有多个参数,并且最后一个参数的选择器片段是以下之一,则Swift将该方法作为异步方法导入:
completion
withCompletion
completionHandler
withCompletionHandler
completionBlock
withCompletionBlock
replyTo
withReplyTo
reply
replyTo
Swift方法的名称是从Objective-C方法修改而来的,如下所示:
The selector piece for the completion handler is removed.
If the selector starts with get, that prefix is removed and leading initialisms are converted to lowercase.
If the selector ends with Asynchronously, that suffix is removed.
If the method calls its completion handler with a nullable parameter, the asynchronous version in Swift is marked with the @discardableResult attribute.