Swift Objective-C任择议定书方法的默认实现

Swift Objective-C任择议定书方法的默认实现,swift,protocols,Swift,Protocols,如何为Objective-C可选协议方法提供默认实现 前 期望值:任何符合AVSpeechSynthezerDelegate的类都应该在演讲结束时运行上述函数。您完全按照实现它的方式来执行。不同之处在于方法的实际调用方式 让我们举一个非常简单的例子: @objc protocol FooProtocol { optional func bar() -> Int } class Omitted: NSObject, FooProtocol {} class Implemented:

如何为Objective-C可选协议方法提供默认实现


期望值:任何符合AVSpeechSynthezerDelegate的类都应该在演讲结束时运行上述函数。

您完全按照实现它的方式来执行。不同之处在于方法的实际调用方式

让我们举一个非常简单的例子:

@objc protocol FooProtocol {
    optional func bar() -> Int
}

class Omitted: NSObject, FooProtocol {}
class Implemented: NSObject, FooProtocol {
    func bar() -> Int {
        print("did custom bar")
        return 1
    }
}
通过不添加其他代码,我希望必须使用以下代码:

let o: FooProtocol = Omitted()
let oN = o.bar?()

let i: FooProtocol = Implemented()
let iN = i.bar?()
其中上的
中的
最后都有类型
Int?
上的
nil
中的
1
,我们看到文本
“did custom bar”
打印出来

重要的是,不是可选的链接方法调用:
bar?()
,即括号中方法名称之间的问号。这就是我们必须从Swift调用可选协议方法的方式

现在,让我们为协议添加一个扩展:

extension FooProtocol {
    func bar() -> Int {
        print("did bar")
        return 0
    }
}
如果我们坚持我们的原始代码,在那里我们可以选择链接方法调用,那么行为没有变化:

然而,随着协议的扩展,我们不再需要有选择地展开。我们可以将可选的展开取出,扩展名为:

不幸的是,这并不一定特别有用,不是吗?现在我们每次只调用扩展中实现的方法

因此,如果您使用协议和调用方法来控制类,那么有一个稍微好一点的选项。您可以检查类是否响应选择器:

let i: FooProtocol = Implemented()

if i.respondsToSelector("bar") {
    i.bar?()
}
else {
    i.bar()
}

这也意味着您必须修改协议声明:

@objc protocol FooProtocol: NSObjectProtocol
添加
NSObjectProtocol
允许我们调用
respondsToSelector
,并且根本不会改变我们的协议。为了实现标记为
@objc
的协议,我们必须从
NSObject
继承


当然,尽管如此,任何Objective-C代码都无法在您的Swift类型上执行此逻辑,并且可能无法实际调用这些协议扩展中实现的方法。因此,如果你试图从苹果的框架中获得一些东西来调用扩展方法,那么你似乎运气不好。而且,即使您试图在Swift中调用其中一个,如果它是协议方法标记为
可选
,似乎也没有很好的解决方案。

谢谢您的详细解释!因此,如果我们不能像苹果的框架一样控制
协议
,我们似乎无法为它们提供默认实现。你可以。您不能在
@objc
协议中提供可选方法的默认实现,任何不知道扩展的代码都会调用这些方法。必须知道扩展名,因为只有Swift才能编写正确的代码来调用这两个扩展名(据我所知),如果Swift不知道扩展名,则无法编译调用这两个扩展名的正确代码。是的。我指的是可选方法。谢谢
@objc protocol FooProtocol: NSObjectProtocol