objective-c - 带有尾随闭包的 Swift 到 Objective-C 调用调用了错误的方法

标签 objective-c swift

给出以下 Objective-C 方法

@import Foundation;

NS_ASSUME_NONNULL_BEGIN

@interface TestClass : NSObject
// Variant 1. Notice that arg1 is nullable, and that all closure arguments are nullable.
+ (void)test:(NSString *_Nullable)arg1
                 action:(nullable void (^)(void))action;

// Variant 2. Notice that arg2 is non null, there is an additional, nullable, closure argument
+ (void)test:(NSString *)title
      action:(nullable void (^)(void))action
     action2:(nullable void (^)(void))action2;

@end

NS_ASSUME_NONNULL_END

我发现,当我尝试使用完全指定的参数从 Swift 调用第一个方法时,当我使用尾随闭包时,它实际上调用了第二个变体

// Calls first variant (This is an erroneous claim, hence Matt's answer)
TestClass.test("arg1", action: {})

// Calls second variant
TestClass.test("arg2") {}

我预计在这两种情况下都会调用变体 1。我不清楚我是否做错了什么。我似乎还错过了这样一个事实:Swift 在调用 Obj-C 方法时可以提供生成参数,并且正在努力寻找相关文档。

如果我将 Obj-C TestClass 替换为等效的


class TestClass {
    class func test(_ arg1: String?, action: (() -> ())? = nil) {
        
    }

    class func test(_ arg1: String!, action: (() -> ())? = nil, action2: (() -> ())? = nil) {
        // Should not get here
        assert(false)
    }

}

然后,我收到编译器警告,称两次调用中“test”的使用不明确。

在 Xcode 12.3 和 12.4 上测试。

最佳答案

Obviously, I expect Variant 1 to be called in both cases.

实际上,我发现在这两种情况下都会调用变体 2。

首先为您的 Objective-C 接口(interface)生成 Swift 接口(interface)。你得到这个:

open class func test(_ arg1: String?, action: (() -> Void)? = nil)
open class func test(_ title: String, action: (() -> Void)?, action2: (() -> Void)? = nil)

我们现在已经从故事中删除了 Objective-C 组件,并且可以在我们的测试中使用这些方法:

typealias VoidVoid = () -> Void
func test(_ arg1: String?, action: VoidVoid? = nil) { print("1") }
func test(_ title: String, action: VoidVoid?, action2: VoidVoid? = nil) { print("2") }
func f() {
    test("arg1", action: {})
    test("arg2") {}
}

如果我们调用f(),控制台会打印“2”两次。我没有收到任何编译错误,但除非您省略两个函数参数,否则第一个变体似乎无法访问。

关于objective-c - 带有尾随闭包的 Swift 到 Objective-C 调用调用了错误的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66091686/

相关文章:

objective-c - 如何从另一个 NSString 中删除 NSString 的文本

ios - 从 InputStream 中获取数据

swift - 如何切掉 UIButton 的角,而不是圆角?

ios - 不使用 Firebase 身份验证的实时数据库的 Firebase 规则

ios - 通过桥接 header 导入到 Swift 项目的 Objective C 库只能在 AppDelegate 中看到,而在其他类中看不到

ios - XCode Objective-C Apple Mach-O 链接器错误

objective-c - 将方法作为参数传递

iOS UIView 没有立即更新

iphone - iPhone 上的文字转语音

ios - Swift - 如何从语音保存文本文件