【问题标题】:Swift 3 API renaming in subclasses子类中的 Swift 3 API 重命名
【发布时间】:2017-02-14 13:10:01
【问题描述】:

我在我的代码中遇到了一些意外行为,其中只有在我使用 Swift 3 之前的方法签名时才会收到 UICollectionViewDelegate 回调。

为了演示这个问题,我创建了两个视图控制器子类:

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    @IBOutlet var collectionView: UICollectionView!

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 100
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        return collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
    }

//  func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
//      print(#function)
//  }
}

class SubViewController: ViewController {

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        print(#function)
    }

    func collectionView(_ collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: IndexPath) {
        print(#function)
    }
}

感兴趣的回调是collectionView(_:willDisplay:forItemAt:) 方法。

首先要注意的是,如果我将该方法的旧变体 (collectionView(_:willDisplayCell:forItemAtIndexPath:)) 添加到 ViewController,编译器会提醒我该方法已重命名:

'collectionView(_:willDisplayCell:forItemAtIndexPath:)' has been renamed to 'collectionView(_:willDisplay:forItemAt:)'

但是,将相同的方法添加到 SubViewController 不会产生任何警告——它似乎会像对待任何其他以前未定义的方法一样对待它。

如果我使用 ViewController 的实例运行应用程序(在此处取消注释 collectionView(_:willDisplay:at:) 方法,并在 SubViewController 中将其注释掉),则会调用正确的委托方法(使用新方法名称)。如果我改用 SubViewController 类,则会调用不正确的委托方法(使用旧方法名称)。

这是正确的行为吗?如果是这样,为什么?这让我很难推断我应该使用哪些方法签名,尤其是在似乎没有对SubViewController 中实际调用的方法进行编译时检查时。

【问题讨论】:

  • 当我复制你的例子时,我在 SubViewController 方法上得到一个错误。 collectionView(_:willDisplay:forItemAt:) 有错误 Overriding declaration requires an 'override' keywordcollectionView(_:willDisplayCell:forItemAtIndexPath:) 有错误 Method 'collectionView(_:willDisplayCell:forItemAtIndexPath:)' with Objective-C selector 'collectionView:willDisplayCell:forItemAtIndexPath:' conflicts with method 'collectionView(_:willDisplay:forItemAt:)' with the same Objective-C selector。 Xcode 8.0。
  • @MikeTaverne 抱歉,您需要注释掉当前未测试的类中的方法。我在对问题的编辑中更清楚地说明了这一点。
  • 在子类中新名称的方法上方添加@objc (collectionView:willDisplayCell:forItemAtIndexPath:)(并删除旧名称的方法)使得新名称的方法被调用。只是想添加一些我发现的信息。
  • 显然 Swift 3 方法名称转换规则不适用于 在运行时。这应该是一个错误。
  • 感谢您填写该错误报告。还有另一个问题,SR-2817,涉及协议和扩展中可能实际相关的 Swift 方法重命名。

标签: ios swift methods uicollectionview subclass


【解决方案1】:

正如其中一个 cmets 所指出的,解决此问题的方法是在这样的函数前面添加@objc

@objc (collectionView:willDisplayCell:forItemAtIndexPath:)
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    // code goes here
}

【讨论】:

    猜你喜欢
    • 2015-01-30
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-21
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多