在 Swift 中使用 Obj-C 完成块
Using Obj-C completion block in Swift
在 Objective-C 中,我有一个完成块 class 定义为:
File.h
typedef void (^MYCompletionBlock)(BOOL success, NSDictionary *result, NSError *error);
然后,在 Swift 文件中,我尝试按如下方式使用完成块:
Swift.swift
class MyClass: NSObject{
...
func MyFunction() -> Void {
...
objcMethod(param1, withCompletion: {(MYCompletionBlock) -> Void in
if (success){ // Error:"Use of unresolved identifier 'success'"
}
}
...
}
...
}
但是,我不断收到错误消息:"Use of unresolved identifier 'success'"。
我也试过以下方法:
objcMethod(param1, withCompletion: {(success:Bool, result: NSDictionary, error:NSError) -> Void in
if (success){ // Error:"Cannot convert value of type '(Bool, NSDictionary, NSError) -> Void' to expected argument type "MYCompletionBlock!"
}
}
有人可以帮助我了解如何在 Swift 中正确指定 Obj-C 完成块吗?
您不应该为完成块参数指定类型,因为某些类型在 Swift 和 Objective C 之间延迟(例如 BOOL
实际上是 ObjCBool
在 Swift).
这应该有效:
objcMethod(param1) { (success, result, error) in
if (success){
// Do something
}
}
鉴于您的闭包没有指定可空性限定符(它们几乎肯定是可选的),我们可以放心地假设您的 Objective-C API 没有针对可空性进行审计。因此,Swift 会将指针视为隐式展开的可选值。此外,如今 NSDictionary
被映射到 [NSObject : AnyObject]
Swift 字典。
因此,它将是:
obj.objcMethod(param) { (success: Bool, result: [NSObject : AnyObject]!, error: NSError!) in
if success {
// do something
}
}
或者,正如 Kobi 指出的那样,您可以让编译器推断类型:
obj.objcMethod(param) { success, result, error in
if success {
// do something
}
}
请注意,您不必自己记住这一点。您可以在输入代码时利用 Xcode 的代码完成功能。因此,键入足以匹配方法名称的内容,当它匹配 objcMethod
时,然后按回车键:
当您到达 MYCompletionBlock
时,再次按回车键,它将显示正确的签名:
如果这个 Objective-C 方法是我自己的 class,我会审核它的可空性。因此,例如,假设 param
是可选的,闭包是必需的,而 result
和 error
是可选的,您可以这样定义它:
NS_ASSUME_NONNULL_BEGIN
typedef void (^MYCompletionBlock)(BOOL success, NSDictionary * _Nullable result, NSError * _Nullable error);
@interface MyObject : NSObject
- (void)objcMethod:(NSDictionary * _Nullable)param1 withCompletionHandler:(MYCompletionBlock)completionHandler;
@end
NS_ASSUME_NONNULL_END
而且,如果是这种情况,您的 Swift 代码会这样调用它:
obj.objcMethod(param) { (success: Bool, result: [NSObject : AnyObject]?, error: NSError?) in
if success {
// do something
}
}
或者,再次让编译器为您推断类型(但这次它们将被推断为未隐式展开的可选类型):
obj.objcMethod(param) { success, result, error in
if success {
// do something
}
}
在 Objective-C 中,我有一个完成块 class 定义为:
File.h
typedef void (^MYCompletionBlock)(BOOL success, NSDictionary *result, NSError *error);
然后,在 Swift 文件中,我尝试按如下方式使用完成块:
Swift.swift
class MyClass: NSObject{
...
func MyFunction() -> Void {
...
objcMethod(param1, withCompletion: {(MYCompletionBlock) -> Void in
if (success){ // Error:"Use of unresolved identifier 'success'"
}
}
...
}
...
}
但是,我不断收到错误消息:"Use of unresolved identifier 'success'"。
我也试过以下方法:
objcMethod(param1, withCompletion: {(success:Bool, result: NSDictionary, error:NSError) -> Void in
if (success){ // Error:"Cannot convert value of type '(Bool, NSDictionary, NSError) -> Void' to expected argument type "MYCompletionBlock!"
}
}
有人可以帮助我了解如何在 Swift 中正确指定 Obj-C 完成块吗?
您不应该为完成块参数指定类型,因为某些类型在 Swift 和 Objective C 之间延迟(例如 BOOL
实际上是 ObjCBool
在 Swift).
这应该有效:
objcMethod(param1) { (success, result, error) in
if (success){
// Do something
}
}
鉴于您的闭包没有指定可空性限定符(它们几乎肯定是可选的),我们可以放心地假设您的 Objective-C API 没有针对可空性进行审计。因此,Swift 会将指针视为隐式展开的可选值。此外,如今 NSDictionary
被映射到 [NSObject : AnyObject]
Swift 字典。
因此,它将是:
obj.objcMethod(param) { (success: Bool, result: [NSObject : AnyObject]!, error: NSError!) in
if success {
// do something
}
}
或者,正如 Kobi 指出的那样,您可以让编译器推断类型:
obj.objcMethod(param) { success, result, error in
if success {
// do something
}
}
请注意,您不必自己记住这一点。您可以在输入代码时利用 Xcode 的代码完成功能。因此,键入足以匹配方法名称的内容,当它匹配 objcMethod
时,然后按回车键:
当您到达 MYCompletionBlock
时,再次按回车键,它将显示正确的签名:
如果这个 Objective-C 方法是我自己的 class,我会审核它的可空性。因此,例如,假设 param
是可选的,闭包是必需的,而 result
和 error
是可选的,您可以这样定义它:
NS_ASSUME_NONNULL_BEGIN
typedef void (^MYCompletionBlock)(BOOL success, NSDictionary * _Nullable result, NSError * _Nullable error);
@interface MyObject : NSObject
- (void)objcMethod:(NSDictionary * _Nullable)param1 withCompletionHandler:(MYCompletionBlock)completionHandler;
@end
NS_ASSUME_NONNULL_END
而且,如果是这种情况,您的 Swift 代码会这样调用它:
obj.objcMethod(param) { (success: Bool, result: [NSObject : AnyObject]?, error: NSError?) in
if success {
// do something
}
}
或者,再次让编译器为您推断类型(但这次它们将被推断为未隐式展开的可选类型):
obj.objcMethod(param) { success, result, error in
if success {
// do something
}
}