首页 文章

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

提问于
浏览
1

我似乎可以在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 回答

  • 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
    
  • 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:

相关问题