首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当外部委托没有实现相同的方法时,不触发带有内部委托的UICollectionView子类

当外部委托没有实现相同的方法时,不触发带有内部委托的UICollectionView子类
EN

Stack Overflow用户
提问于 2022-10-25 12:34:06
回答 1查看 94关注 0票数 1

我正在为UICollectionViewDelegate开发一个第三方框架,所以我不能亲自使用的委托方法,但是我确实需要它们来实现一些自定义逻辑。

尝试了多种方法来使其工作,包括方法swizzling,但最终我觉得它对我所做的工作来说太麻烦了。

现在,我对UICollectionView进行子类化,并将委托设置为内部(我的)委托。除了当UIViewController还没有实现该方法之外,这个方法工作得很好。

现在,我的代码如下所示:

代码语言:javascript
运行
复制
fileprivate class UICollectionViewDelegateInternal: NSObject, UICollectionViewDelegate {
    var userDelegate: UICollectionViewDelegate?
    
    override func responds(to aSelector: Selector!) -> Bool {
        return super.responds(to: aSelector) || userDelegate?.responds(to: aSelector) == true
    }
    
    override func forwardingTarget(for aSelector: Selector!) -> Any? {
        if userDelegate?.responds(to: aSelector) == true {
            return userDelegate
        }
        return super.forwardingTarget(for: aSelector)
    }
    
    func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        let collection = collectionView as! CustomCollectionView
        collection.didEnd(item: indexPath.item)
        userDelegate?.collectionView?(collectionView, didEndDisplaying: cell, forItemAt: indexPath)
    }
}

class CustomCollectionView: UICollectionView {
    private let internalDelegate: UICollectionViewDelegateInternal = UICollectionViewDelegateInternal()
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        super.delegate = internalDelegate
    }
    
    override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
        super.init(frame: frame, collectionViewLayout: layout)
        super.delegate = internalDelegate
    }

    
    
    func didEnd(item: Int) {
        print("internal - didEndDisplaying: \(item)")
    }
    
    
    override var delegate: UICollectionViewDelegate? {
        get {
            return internalDelegate.userDelegate
        }
        set {
            self.internalDelegate.userDelegate = newValue
            super.delegate = nil
            super.delegate = self.internalDelegate
        }
    }
}

ViewController中,我只使用未实现的didEndDisplaying委托方法进行了简单的设置

在没有实现didEndDisplaying的情况下,可以听ViewController吗?

编辑1:

下面是ViewController的代码,让它更清楚一些我在做什么

代码语言:javascript
运行
复制
class ViewController: UIViewController {
    @IBOutlet weak var collectionView: CustomCollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.dataSource = self
        collectionView.delegate = self
    }
}


extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        1000
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
                cell.backgroundColor = .blue
                return cell
    }
    
//    func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
//        print("view controller - did end displaying: \(indexPath.item)")
//    }
}

只有当我取消对didEndDisplaying中的didEndDisplaying方法进行注释时,才会触发didEndDisplaying方法。

我正在寻找的是,如果didEndDisplaying中的didEndDisplaying方法没有实现,那么也会触发ViewControllerdidEndDisplaying

希望现在更清楚一点

编辑2:

发现上面的代码有一些错误,使复制不能像我想的那样工作。更新了上述代码。还创建了一个github页面,以便在这里更容易地复制:https://github.com/mees-vdb/InternalCollectionView-Delegate

EN

Stack Overflow用户

回答已采纳

发布于 2022-11-17 16:58:17

我阅读了一下这个方法,似乎应该能工作,但很明显,它不起作用。

玩了一会儿,这可能是你的解决方案。

我对您现有的代码做了很少的更改(从GitHub抓取它--如果您想将我作为协作者添加,我可以在GitHub上推送一个相同的DonMag ID的新分支)。

首先,我实现了didSelectItemAt,以使调试变得更容易(一次只有一个事件)。

ViewController类

代码语言:javascript
运行
复制
class ViewController: UIViewController {
    @IBOutlet weak var collectionView: CustomCollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.dataSource = self
        collectionView.delegate = self
    }
}


extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        1000
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.backgroundColor = .blue
        return cell
    }
    
    // DonMag - comment / un-comment these methods
    //  to see the difference
    
    //func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    //  print("view controller - did end displaying: \(indexPath.item)")
    //}
    
    //func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    //  print("view controller - didSelectItemAt", indexPath)
    //}
}

UICollectionViewDelegateInternal类

代码语言:javascript
运行
复制
fileprivate class UICollectionViewDelegateInternal: NSObject, UICollectionViewDelegate {
    var userDelegate: UICollectionViewDelegate?
    
    override func responds(to aSelector: Selector!) -> Bool {
        return super.responds(to: aSelector) || userDelegate?.responds(to: aSelector) == true
    }
    
    override func forwardingTarget(for aSelector: Selector!) -> Any? {
        if userDelegate?.responds(to: aSelector) == true {
            return userDelegate
        }
        return super.forwardingTarget(for: aSelector)
    }
    
    func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        let collection = collectionView as! CustomCollectionView
        collection.didEnd(item: indexPath.item)
        userDelegate?.collectionView?(collectionView, didEndDisplaying: cell, forItemAt: indexPath)
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let collection = collectionView as! CustomCollectionView
        collection.didSel(p: indexPath)
        userDelegate?.collectionView?(collectionView, didSelectItemAt: indexPath)
    }
    
}

CustomCollectionView类

代码语言:javascript
运行
复制
// DonMag - conform to UICollectionViewDelegate
class CustomCollectionView: UICollectionView, UICollectionViewDelegate {
    private let internalDelegate: UICollectionViewDelegateInternal = UICollectionViewDelegateInternal()
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        super.delegate = internalDelegate
    }
    
    override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
        super.init(frame: frame, collectionViewLayout: layout)
        super.delegate = internalDelegate
    }
    
    func didEnd(item: Int) {
        print("internal - didEndDisplaying: \(item)")
    }
    
    func didSel(p: IndexPath) {
        print("internal - didSelectItemAt", p)
    }
    
    // DonMag - these will NEVER be called,
    //  whether or not they're implemented in
    //  UICollectionViewDelegateInternal and/or ViewController
    // but, when implemented here,
    //  it allows (enables?) them to be called in UICollectionViewDelegateInternal
    func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        print("CustomCollectionView - didEndDisplaying", indexPath)
    }
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("CustomCollectionView - didSelectItemAt", indexPath)
    }
    
    override var delegate: UICollectionViewDelegate? {
        get {
            // DonMag - return self instead of internalDelegate.userDelegate
            return self
            //return internalDelegate.userDelegate
        }
        set {
            self.internalDelegate.userDelegate = newValue
            super.delegate = nil
            super.delegate = self.internalDelegate
        }
    }
}
票数 3
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74194162

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档