微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swift尝试在Objective-C块中

我需要创建一个函数foo,它将一个抛出闭包作为参数.我可以使用 Swift或ObjC实现它,但我需要能够从两者中调用它.

像这样:

// Swift
func bar() throws
func foo(_ block: () throws -> void)

foo {
  try bar()
}

// Objc
[self foo:^(
  [other barBar];
)];

我尝试用Swift和ObjC实现它而没有成功.使用Swift:

@objc
func foo(block: () throws -> Void)

我收到此错误

Method cannot be marked @objc because the type of the parameter 1 cannot be represented in Objective-C

如果我尝试用ObjC实现它:

typedef BOOL (^ThrowingBlock)(NSError **);
- (void)foo:(ThrowingBlock)block;

然后它不会转换为抛出的块(as it would with a function):

func foo(_: (NSErrorPointer) -> Bool)

知道怎么做到这一点?

解决方法

您可以使用NS_REFINED_FOR_SWIFT宏在Objective-C和Swift之间提供统一的接口,在Objective-C中抛出Swift和NSError **.

Apple documentation

You can use the NS_REFINED_FOR_SWIFT macro on an Objective-C method declaration to provide a refined Swift interface in an extension,while keeping the original implementation available to be called from the refined interface. For instance,an Objective-C method that takes one or more pointer arguments Could be refined in Swift to return a tuple of values.

在你的情况下,你可以将foo声明为Swift的精炼,并在类扩展中添加相同的方法

@interface MyClass : NSObject

- (void)foo:(void (^)(NSError **))block NS_REFINED_FOR_SWIFT;

@end

在斯威夫特:

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
            }
        }
    }
}

现在你可以从两个世界调用foo,区别在于Objective-C代码需要传递NSError **块,而Swift调用者可以通过更好的抛出关闭.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐