给出以下 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/