在Objective-C块内快速尝试 [英] Swift try inside Objective-C block

查看:75
本文介绍了在Objective-C块内快速尝试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要创建一个函数 foo ,该函数将引发闭包作为参数。我可以使用Swift或ObjC来实现它,但是我需要能够从两者中调用它。

I need to create a function foo that takes a throwing closure as a parameter. I can implement it with either Swift or ObjC but I need to be able to call it from both.

就像这样:

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

foo {
  try bar()
}

and

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

我试图用Swift和ObjC来实现它而没有成功。使用Swift:

I tried to implement it with both Swift and ObjC without succes. With Swift:

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

我收到此错误:


不能将方法标记为@objc,因为参数1的类型不能在Objective-C中表示。

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

如果我尝试实现它与ObjC:

If I try to implement it with ObjC:

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

然后它不会转换为抛出的块(就像使用函数一样):

Then it does not translate to a block that throws (as it would with a function):

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

有什么办法实现这一目标吗?

Any idea how to achieve this?

推荐答案

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

You could use the NS_REFINED_FOR_SWIFT macro to provide a unified interface between Objective-C and Swift, with throws in Swift and NSError ** in Objective-C.

Apple文档


您可以在Objective-C方法上使用NS_REFINED_FOR_SWIFT宏声明以在扩展中提供精致的Swift接口,同时保持原始实现n可从改进的界面调用。例如,可以在Swift中对采用一个或多个指针参数的Objective-C方法进行改进,以返回一个元组值。

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进行了精炼,并在类扩展中添加了相同的方法:

In your case you can declare foo as refined for Swift, and add a same method, in a class extension:

@interface MyClass : NSObject

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

@end

以及在Swift中:

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调用者可以通过更好的抛出闭包。

Now you can call foo from both worlds, with the distinction that Objective-C code will need to pass a NSError ** block, while Swift callers can pass a nicer throws closure.

这篇关于在Objective-C块内快速尝试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆