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

时间:2015-01-17 05:40:05

标签: ios objective-c swift init

我遇到了一个问题,即获取需要由JSONJoy协议实现的Swift init方法的Objective-C选择器。我希望能够获得init方法的选择器的原因是我可以基于类名来以编程方式实例化Swift类,这在Swift API中是不可能的,因此需要转到Objective-C来做到这一点。我在https://gist.github.com/BennettSmith/1613121使用例程打印出每个类及其父类的所有方法,并且选择器总是显示为“init”,但根据我的理解,它应该显示为“init: “因为它有一个参数。

JSONJoy协议是:

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

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

init(str: String) {}显示选择器为“initWithStr:”

required public init(str: String) {}仍显示“initWithStr:”

的选择器

取消协议并使用方法签名“init(str:String)”直接在我的类中实现方法,它仍然显示为“initWithStr:”。< /强>

使用和不使用“TestProtocol”的所有上述测试都按预期生成选择器。

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

2 个答案:

答案 0 :(得分:1)

要在Objective-C中提供Swift协议,您需要将@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

答案 1 :(得分:0)

具有第一个参数且外部参数名称为foo(即init(foo bar:Int))的初始值设定项在Objective-C中默认为initWithFoo:。如果未明确指定初始化程序参数的外部名称,则将隐式使外部名称与内部名称相同。因此,当您编写init(str: String)时,它隐式init(str str: String),您必须像MyClass(str: something)一样使用它,而Objective-C选择器是initWithStr:

您始终可以使用_显式禁止外部名称,您可以在其中指定外部名称。这就是他们对JSONJoyinit(_ decoder: JSONDecoder))中初始值设定项的第一个参数所做的操作。你可以做同样的事情:

init(_ str: String)

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