简体   繁体   中英

UICollectionView delegate methods never called when inheriting from a generic class

I have a generic class named GenericView<Key: Equatable> which conforms to UICollectionViewDelegateFlowLayout protocol and holds a collectionview. Then I have a NewView class inherits from GenericView<Key: Equatable> .

The problem is, delegate methods implemented within NewView class never get called if they doesn't exist in GenericView<Key: Equatable> . UIScrollView delegate methods never get called as well, unless they has an @objc prefix. However, the @objc prefix doesn't solve the UICollectionView delegate issue.

Simple Code:

// 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)")
    }
}

Although UICollectionViewDelegateFlowLayout inherits from UIScrollViewDelegate , they have different behaviors in the above code.

I find this: https://bugs.swift.org/browse/SR-2817 . The bug was reported in 2016.

It seems that this is not a UICollectionView issue, but a issue which exists in Swift and Objective-C interaction.

I wonder if this is an issue which will be solved in the future, or it's a feature and I should prevent writing code in this way. This really confuses me and wastes lots of time. Generic type is a great idea and is widely used in programming.

The problem is UICollectionViewDelegateFlowLayout delegated are being set to the delegates of GenericView . But NewView has another set of methods which are not confirmed to UICollectionViewDelegateFlowLayout of the collectionView . To make it work you need to add prefix override in front of the UICollectionViewDelegateFlowLayout methods in NewView

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM