【问题标题】:Adding function signatures to existing protocols in Swift向 Swift 中的现有协议添加函数签名
【发布时间】:2018-03-14 04:10:04
【问题描述】:

我们有一个包含许多 NSCollectionViews 的大型代码库,我们希望添加一个功能来使用键盘控制 views,同时尽可能少地更改代码。

为此,我们希望处理一个文件中的键,并通过委托协议简单地触发“Action Fired”事件。我们的NSCollectionView 已经实现了NSCollectionViewDelegate protocol,因此我们希望将事件直接添加到该协议中,而不是通过继承来实现。

现在,我知道您可以使用 extension 关键字扩展协议:

extension NSCollectionViewDelegate {
    func collectionView(_ collectionView: NSCollectionView, didMoveLeft: Bool) {
        // Default implementation here
    }
}

这种方法的问题在于,由于原始协议中没有声明签名,因此将始终调用默认实现,即使一个类实现了它自己的。

那么真正扩展协议功能的最佳方法是什么,以便我现有的所有NSCollectionViews 能够在不继承protocol 的情况下实现自己的行为?

到目前为止,我发现“最好的方法”是编写以下内容:

extension NSCollectionView {
    override open func moveLeft(_ sender: Any?) {
        (delegate as? NSCollectionViewDelegateExtended)?.collectionView(self, didMoveLeft: true)
    }
}

protocol NSCollectionViewDelegateExtended : NSCollectionViewDelegate {
    func collectionView(_ collectionView: NSCollectionView, didMoveLeft: Bool)
}

然后实现NSCollectionViewDelegateExtended而不是NSCollectionViewDelegate

extension CustomViewController: NSCollectionViewDelegateExtended {
    func collectionView(_ collectionView: NSCollectionView, didMoveLeft: Bool) {
        // Implementation here
    }
}

但这不是我想要的。有没有更好的方法将新功能无缝嵌入NSCollectionViewDelegate

【问题讨论】:

    标签: swift cocoa inheritance swift-protocols


    【解决方案1】:

    一种解决方案是将新的委托方法添加为optional。请记住,为了做到这一点,您必须为objective-C 打开您的协议。这可以像下面这样完成

    @objc protocol MyProtocol {
        //older method 1
        //older method 2
        //...
        //older method X
    
        @objc optional func newMethod()
    }
    

    【讨论】:

      【解决方案2】:

      你确定这是真的吗?

      这种方法的问题在于,由于签名没有 在原始协议中已声明,默认实现 总是会被调用,即使一个类实现了它自己的。

      我做了一个快速测试,扩展协议方法的自定义实现被调用了。

      protocol AProtocol: class {
          func baseMethod()
      }
      
      extension AProtocol {
          func extendenMethod() {
              print("Extended default implementation")
          }
      }
      
      class A: NSObject, AProtocol {
          func baseMethod() {
              print("Base")
          }
          func extendenMethod() {
              print("Extended custom implementation")
          }
      }
      
      let a = A()
      
      a.baseMethod()
      a.extendenMethod()
      

      结果:

      根据 扩展自定义实现

      【讨论】:

      • 啊,我应该更清楚。如果您直接在类上调用该方法,它可以正常工作,但如果您从协议调用该方法并且该类不知道具体类型,它将调用默认实现,这是正常的并且是设计使然。
      猜你喜欢
      • 2015-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      相关资源
      最近更新 更多