Swift 来自 JSONJoy 协议的初始化方法不能用作 Objective-C 选择器

Swift init method from JSONJoy protocol not available as Objective-C selector

我在为需要由 JSONJoy 协议实现的 Swift init 方法获取 Objective-C 选择器时遇到问题。我希望能够获得 init 方法的选择器的原因是,我可以根据 class 名称以编程方式实例化 Swift class,这在Swift API 所以需要下到 Objective-C 去做。我正在使用 https://gist.github.com/BennettSmith/1613121 处的例程打印出每个 class 及其父 classes 的所有方法,并且选择器始终显示为 "init",但是从我的理解应该显示为 "init:" 因为它有一个参数。

JSONJoy 协议是:

public protocol JSONJoy {
    init(_ decoder: JSONDecoder)
}

为了测试,我尝试创建自己的名为 "TestProtocol" 的协议。以下是我的结果。

init(str: String) {} 显示 "initWithStr:"

选择器

required public init(str: String) {} 仍然显示 "initWithStr:"

选择器

删除协议并直接在我的 class 中使用方法签名 "init(str: String)" 实现方法,它仍然显示为 "initWithStr:".

以上所有带和不带 "TestProtocol" 的测试都按预期生成选择器。

但是,无论我如何操作 JSONJoy 协议签名,当我列出 [=53] 的选择器时,它总是显示为没有任何参数的普通 "init" =].我尝试删除“_”并向协议添加其他参数,但它仍然显示为 "init"

要使 Swift 协议在 Objective-C 中可用,您需要将 @objc 属性添加到协议声明中。

您可以使用 respondsToSelector() 测试 Objective-C 方法签名,如以下 Playground 示例所示:

@objc protocol Foo 
{
    init(_ someNumber: Int)
}

@objc(MYBar) class Bar : NSObject, Foo 
{
    required init(_ someNumber: Int) 
    {
        println("Got \(someNumber)")
    }
}

var bar = Bar(123)
bar.respondsToSelector("init:") // true
NSClassFromString("MYBar")?.alloc() // `Bar` instance

第一个参数的初始化器的外部参数名称为foo(即init(foo bar:Int)),在Objective-C中默认变为initWithFoo:。当您没有为初始化参数显式指定外部名称时,外部名称将隐式地与内部名称相同。所以当你写init(str: String)的时候,隐含的是init(str str: String),你要像MyClass(str: something)一样使用,而Objective-C选择器是initWithStr:.

您始终可以通过在指定外部名称的地方使用 _ 显式禁止显示外部名称。这就是他们对 JSONJoy (init(_ decoder: JSONDecoder)) 中初始化程序的第一个参数所做的事情。你可以做同样的事情:

init(_ str: String)

然后你会像 MyClass(something) 一样使用它,Objective-C 选择器将是 init: