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:
我在为需要由 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: