我遇到了一个问题,即获取需要由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”
答案 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:
。
您始终可以使用_
显式禁止外部名称,您可以在其中指定外部名称。这就是他们对JSONJoy
(init(_ decoder: JSONDecoder)
)中初始值设定项的第一个参数所做的操作。你可以做同样的事情:
init(_ str: String)
然后你会像MyClass(something)
一样使用它,而Objective-C选择器将是init: