异步调用Objective-C API
apple 发布于 2024-05-06

概述

在Cocoa中,执行异步操作的方法将完成处理程序作为其最后一个参数,该方法在操作完成后调用该块以返回结果或错误。Swift 5.5及更高版本使用Swift的本地并发支持,除了将基于回调的方法版本导入Swift之外,还自动将使用完成处理程序的Objective-C方法转换为异步方法。因为两个Swift方法具有相同的行为,所以它们在文档中共享相同的页面。

有关异步函数的信息,请参阅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)

了解转换规则

采用完成处理程序的方法必须满足以下要求:

  • 该方法具有void返回类型。
  • 块具有void返回类型。
  • 在控制流的所有可能路径上,该块只被调用一次。
    如果该方法只有一个参数,并且其选择器以以下后缀之一结尾,则Swift将该方法作为异步方法导入:
  • 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.

apple
关注 私信
文章
13
关注
0
粉丝
0