尝试将 Objective C 完成块移植到 Swift 时出现问题

Problems trying to port an Objective C completion block into Swift

我正在使用 objective C 编写的第三方库,方法如下:

- (void)manageServerResponse:(NSURLResponse*)response NSData:(NSData*)data andNSError:(NSError*)error onComplete:(void (^)(NSInteger kindOfError, NSDictionary*jsonResponse))onComplete;

当我将其移植到 swift 时,我执行以下操作:

typealias ResponseCompletedBlock = (NSInteger, NSDictionary?) -> Void
...
let completedResponseMethod : ResponseCompletedBlock = {(kindOfError: NSInteger, jsonResponse: NSDictionary?) -> Void in
    self.onComplete(kindOfError, jsonResponse: jsonResponse)}

let responseManager: ResponseManager = ResponseManager.sharedResponseManager() as! ResponseManager
responseManager.manageServerResponse(response, 
    NSData: data, 
    andNSError: error, 
    onComplete: completedResponseMethod)

我收到这个错误:

Cannot invoke 'manageServerResponse' with an argument list of type '(NSURLResponse?, NSData: NSData?, andNSError: NSError?, onComplete: ResponseCompletedBlock)'

如果我将最后一句替换为

responseManager.manageServerResponse(response, 
    NSData: data, 
    andNSError: error, 
    onComplete: nil)

一切正常,所以我认为问题出在块结构上,但我已尝试更改所有内容,但错误仍然存​​在。

你能帮忙吗?

typealiascompletedResponseMethod 是您的程序运行所必需的吗?如果没有,这可能会解决您的问题:

responseManager.manageServerResponse(response, NSData: data, andNSError: error, onComplete: { 
    [=10=],  in
    self.onComplete([=10=], jsonResponse: )
}

如您的错误所示,错误是由于类型不匹配造成的。如果您使用默认的本地参数,您将能够解决该特定问题。

NSDictionary * 映射到 Swift 作为 [NSObject : AnyObject]!, 因此响应块的类型应该是

typealias ResponseCompletedBlock = (Int, [NSObject : AnyObject]!) -> Void

因此

let completedResponseMethod = {(kindOfError: Int, jsonResponse: [NSObject : AnyObject]!) -> Void in
    // ...
}

找出正确的 Swift 函数签名的一种方法是使用 Xcode 中的 自动完成 : 您开始输入

 responseManager.manageServerResponse(

和Xcode建议

根据 Apple docs:

When you bridge from an NSDictionary object to a Swift dictionary, the resulting dictionary is of type [NSObject: AnyObject].

此外,除非 Objective-C 代码被注释为空性,否则 Swift 字典是一个隐式展开的可选。因此你的类型别名应该是这样的:

typealias ResponseCompletedBlock = (NSInteger, [NSObject : AnyObject]!) -> Void

我还建议将 NSInteger 更改为 Int