【发布时间】: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' keyword。collectionView(_: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