【发布时间】:2020-10-04 10:00:41
【问题描述】:
我有一个名为GenericView<Key: Equatable> 的通用类,它符合UICollectionViewDelegateFlowLayout 协议并拥有一个collectionview。然后我有一个NewView 类继承自GenericView<Key: Equatable>。
问题是,在NewView 类中实现的委托方法如果在GenericView<Key: Equatable> 中不存在,则永远不会被调用。 UIScrollView 委托方法也永远不会被调用,除非它们具有 @objc 前缀。但是,@objc 前缀并不能解决 UICollectionView 委托问题。
简单代码:
// MARK: - Generic Class
class GenericView<Key: Equatable>: UIView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var key: Key?
var collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
override init(frame: CGRect) {
super.init(frame: frame)
// Constraint collection view.
collectionView.translatesAutoresizingMaskIntoConstraints = false
addSubview(collectionView)
NSLayoutConstraint.activate([
collectionView.leadingAnchor.constraint(equalTo: leadingAnchor),
collectionView.topAnchor.constraint(equalTo: topAnchor),
collectionView.trailingAnchor.constraint(equalTo: trailingAnchor),
collectionView.bottomAnchor.constraint(equalTo: bottomAnchor)
])
// Set delegate and data source.
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 100
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
cell.contentView.backgroundColor = .blue
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 100, height: 100)
}
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
print("generic class: \(#function)")
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("generic class: \(#function)")
}
}
// MARK: - SubClass
class NewView: GenericView<String> {
// called
override func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
print("new class: \(#function)")
}
// called
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("new class: \(#function)")
}
// called
@objc func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
print("new class: \(#function)")
}
// not called
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
print("new class: \(#function)")
}
// not called
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
print("new class: \(#function)")
}
// not called
@objc func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
print("new class: \(#function)")
}
}
虽然UICollectionViewDelegateFlowLayout继承自UIScrollViewDelegate,但在上述代码中它们的行为不同。
我发现这个:https://bugs.swift.org/browse/SR-2817。该错误是在 2016 年报告的。
看来这不是UICollectionView的问题,而是Swift和Objective-C交互中存在的问题。
我想知道这是否是一个将来会解决的问题,或者它是一个特性,我应该阻止以这种方式编写代码。这真的让我很困惑,浪费了很多时间。泛型类型是一个好主意,在编程中被广泛使用。
【问题讨论】:
标签: ios swift xcode uicollectionview