iOS Swift中CollectionView的代理未被调用

3

我已经将协议 UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIScrollViewDelegate 确认为一个名为 CollectionViewWeekDelegate 的单独类,但是像 didSelectItemAt 这样的委托方法没有被调用。

我也在 viewDidLoad() 中将代理设置为 CollectionView

请查看以下代码:

委派类

class CollectionViewWeekDelegate: NSObject, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIScrollViewDelegate {

    internal var parent: EarningsViewController?

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        parent?.weekTabSelectedPosition = indexPath.item

        let indexPathh = IndexPath(item: indexPath.item, section: 0)

        parent?.collectionViewSchedule.scrollToItem(at: indexPathh, at: .right, animated: true)
        parent?.collectionViewWeeks.scrollToItem(at: indexPath, at: .top, animated: true)

        parent?.collectionViewWeeks.reloadData()

    }


    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

        let offsetX = parent?.collectionViewSchedule.contentOffset.x
        let contentWidth = parent?.collectionViewSchedule.bounds.width

        let page = Int(offsetX! / contentWidth!)

        parent?.weekTabSelectedPosition = page



        var earningsText  = "\("grossEarnings".localize()) $\(String(format: "%0.2f", 0.0))"

        if let earnings = parent?.schedules?[page].grossWeekSalary{
            earningsText = "\("grossEarnings".localize()) $\(String(format: "%0.2f", earnings))"


            parent?.buttonGrossEarnings.setTitle(earningsText, for: .normal)

            parent?.collectionViewWeeks.selectItem(at: IndexPath(item: page, section: 0), animated: true, scrollPosition: .centeredHorizontally)}
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if collectionView.tag == 2{
            return CGSize(width: UIScreen.main.bounds.width, height: (parent?.collectionViewSchedule.bounds.height)!)
        }else{
            return CGSize(width: 150, height: 50)
        }
    }
}

viewDidLoad 函数中,将 CollectionView 的代理分配给:

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?.title = "schedule".localize()

    self.navigationItem.leftBarButtonItem = super.getMenuBartItem()

    if let flowLayout = collectionViewWeeks.collectionViewLayout as? UICollectionViewFlowLayout{
        flowLayout.estimatedItemSize = CGSize(width: 150, height: 50)
    }

    if let collectionFlowLayout = collectionViewSchedule.collectionViewLayout as? UICollectionViewFlowLayout{
        collectionFlowLayout.minimumLineSpacing = 0
        collectionFlowLayout.minimumInteritemSpacing = 0

    }

    let weekDelegate = CollectionViewWeekDelegate()
    weekDelegate.parent = self

    collectionViewWeeks.delegate = weekDelegate
    collectionViewSchedule.delegate = self

    collectionViewWeeks.reloadData()
}

基本上,CollectionViewWeekDelegate不是UICollectionView的子类,请将您的类设置为UICollectionView的子类,然后进行测试。 - Zulqarnain Mustafa
collectionViewWeeks.delegate 是如何定义的? - Andreas Oetjen
@AndreasOetjen weekDelegate 被分配给了 collectionViewWeeks.delegate。 - Akshay Sood
它是如何声明的?它是“弱引用”吗? - Andreas Oetjen
不,这不是弱项。 - Akshay Sood
2个回答

6

viewDidLoad 执行完毕时,你的 weekDelegate 就会被释放 - 你只保留了一个局部变量,没有强引用。唯一还持有它引用的类是 UICollectionView 本身(在你的情况下是 collectionViewWeeks),但 UICollectionView 将其 delegate 定义为 weak

只需这样保持引用即可:

// create a strong property and use it instead of local variable
fileprivate let weekDelegate = CollectionViewWeekDelegate()

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?.title = "schedule".localize()

    self.navigationItem.leftBarButtonItem = super.getMenuBartItem()

    if let flowLayout = collectionViewWeeks.collectionViewLayout as? UICollectionViewFlowLayout{
        flowLayout.estimatedItemSize = CGSize(width: 150, height: 50)
    }

    if let collectionFlowLayout = collectionViewSchedule.collectionViewLayout as? UICollectionViewFlowLayout{
        collectionFlowLayout.minimumLineSpacing = 0
        collectionFlowLayout.minimumInteritemSpacing = 0

    }

    weekDelegate.parent = self

    collectionViewWeeks.delegate = weekDelegate
    collectionViewSchedule.delegate = self

    collectionViewWeeks.reloadData()
}

@MilanNosal:AkshaySood之前已经说明了(请参见我的问题评论),委托没有弱引用。 - Andreas Oetjen
在AndreasOetjen的代码中,对该委托的唯一引用是他的局部变量。我们能看到的唯一其他引用是UICollectionView.delegate,而且那是一个weak引用。所以我敢打赌这就是问题所在,除非他向我们展示了strong引用的定义位置,否则我必须认为这就是问题所在。 - Milan Nosáľ
@MilanNosal:我非常同意你的观点,这也是我的第一反应,但毫无疑问他在那之前回答了我的问题——它不是弱项。 - Andreas Oetjen
1
@AndreasOetjen 在99%的情况下,代码比作者对代码的假设更好地描述了情况(我也是根据自己的经验说的)... 让他尝试我的建议,我们会看到会发生什么。 - Milan Nosáľ
@AkshaySood 很高兴能帮助。 - Milan Nosáľ

-1
你可以在Cell的awakeFromNib方法中将DataSource和Delegate设置为self,并进行单元格注册。 这样可以解决委托未被调用的问题。 因为当前当你的单元格被出列时,你传递的数据是正确的,但内部的集合视图实例为空,所以它不会调用委托方法。
你可以尝试像这样做。
    class CustomCollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var collectionView: UICollectionView!
    
    private let cellId = "CollectionViewCellID"
       
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        collectionView.delegate = self;
        collectionView.dataSource = self;
        collectionView.register(UINib(nibName: cellId, bundle: nil), forCellWithReuseIdentifier: cellId)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接