tgy*_*lsb 5 error-handling closures objective-c try-catch swift
我需要创建一个foo将抛出闭包作为参数的函数.我可以使用Swift或ObjC实现它,但我需要能够从两者中调用它.
像这样:
// Swift
func bar() throws
func foo(_ block: () throws -> void)
foo {
try bar()
}
Run Code Online (Sandbox Code Playgroud)
和
// Objc
[self foo:^(
[other barBar];
)];
Run Code Online (Sandbox Code Playgroud)
我尝试用Swift和ObjC实现它而没有成功.使用Swift:
@objc
func foo(block: () throws -> Void)
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
方法不能标记为@objc,因为参数1的类型不能在Objective-C中表示
如果我尝试用ObjC实现它:
typedef BOOL (^ThrowingBlock)(NSError **);
- (void)foo:(ThrowingBlock)block;
Run Code Online (Sandbox Code Playgroud)
然后它不会转换为抛出的块(就像使用函数一样):
func foo(_: (NSErrorPointer) -> Bool)
Run Code Online (Sandbox Code Playgroud)
知道怎么做到这一点?
您可以使用该宏在 Objective-C 和 Swift 之间(在 Swift 和Objective-C 中NS_REFINED_FOR_SWIFT)提供统一的接口。throwsNSError **
来自苹果文档:
您可以在 Objective-C 方法声明上使用 NS_REFINED_FOR_SWIFT 宏,在扩展中提供精炼的 Swift 接口,同时保持原始实现可从精炼的接口调用。例如,采用一个或多个指针参数的 Objective-C 方法可以在 Swift 中进行优化以返回一组值。
在您的情况下,您可以声明foo为 Swift 的精炼,并在类扩展中添加相同的方法:
@interface MyClass : NSObject
- (void)foo:(void (^)(NSError **))block NS_REFINED_FOR_SWIFT;
@end
Run Code Online (Sandbox Code Playgroud)
在斯威夫特中:
extension MyClass {
func foo(block: @escaping () throws -> Void) {
// Objective-C's `foo` is now imported as `__foo`
__foo { errPtr in
do {
try block()
} catch {
errPtr?.pointee = error as NSError
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在您可以foo从两个世界进行调用,区别在于 Objective-C 代码需要传递一个NSError **块,而 Swift 调用者可以传递一个更好的throws闭包。
| 归档时间: |
|
| 查看次数: |
342 次 |
| 最近记录: |