UICollectionView numberOfItemsInSection 未在 reloadData() 上调用 - Swift Xcode

问题描述

我有两个视图控制器——SecondTestViewController 和 SecondContentViewController。 SecondContentViewController 是 SecondTestViewController 中的一个浮动面板。 SecondTestViewController 有一个 UITableView,SecondContentViewController 有一个 UICollectionView。

SecondContentViewController:

override func viewDidLoad() {
        super.viewDidLoad()
//        let layout = UICollectionViewFlowLayout()
//        layout.scrollDirection = .vertical
        myCollectionView = UICollectionView(frame: .zero,collectionViewLayout: collectionViewLayout())
        guard let myCollectionView = myCollectionView else {
            return
        }
        myCollectionView.register(CollectionViewCell.self,forCellWithReuseIdentifier: "CollectionViewCell")
        myCollectionView.delegate = self
        myCollectionView.dataSource = self
        myCollectionView.backgroundColor = .white
        myCollectionView.translatesAutoresizingMaskIntoConstraints = false
        myCollectionView.allowsSelection = true
        myCollectionView.isspringLoaded = true
        view.backgroundColor = .white
        view.addSubview(myCollectionView)
        NSLayoutConstraint.activate([
            myCollectionView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),myCollectionView.leftAnchor.constraint(equalTo: self.view.leftAnchor),myCollectionView.rightAnchor.constraint(equalTo: self.view.rightAnchor),myCollectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
        ])
        
    }
    
    private func collectionViewLayout() -> UICollectionViewLayout {
        let layout = UICollectionViewFlowLayout()
        let cellWidthHeightConstant: CGFloat = UIScreen.main.bounds.width * 0.2
        layout.sectionInset = UIEdgeInsets(top: 50,left: 10,bottom: 0,right: 10)
        layout.scrollDirection = .vertical
        layout.minimumInteritemSpacing = 0
        layout.itemSize = CGSize(width: cellWidthHeightConstant,height: cellWidthHeightConstant)
        
        return layout
    }
    
    func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection section: Int) -> Int {
//        return contentData.count
        print("numberOfItemsInSection activated")
        print("numberOfItemsInSection = \(reviewDataController?.tableViewReviewData.count ?? 100)")
        return reviewDataController?.tableViewReviewData.count ?? 0
    }
    
    func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        print("cellForItemAt activated")
        let cell = myCollectionView?.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell",for: indexPath) as! CollectionViewCell
//        cell.data = self.contentData[indexPath.item]
        cell.data = self.reviewDataController.tableViewReviewData[indexPath.item]
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,sizeforItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: collectionView.frame.width / 5,height: collectionView.frame.height / 10)
    }
    
    
    func updateTheCollectionView() {
        print("updateCollectionView activated")
        print("reviewData count = \(reviewDataController.tableViewReviewData.count)")
        myCollectionView?.reloadData()
    }

当 SecondTestViewController 的 tableView 中的单元格被点击时,它会拍照,传递数据,然后调用 SecondContentViewController 的 updateTheCollectionView() 函数

在拍摄照片并完成其他各种任务(如更新变量等)后,在 SecondTestViewController 中调用函数

func passDataToContentVC() {
        let contentVC = SecondContentViewController()
        contentVC.reviewDataController = self.reviewDataController
        contentVC.updateTheCollectionView()
    }

如您所见,应该在此函数内部调用 reloadData。它现在应该使用新照片更新视图。出于某种原因,就像 reloadData 从未被调用过一样,因为 numberOfItemsInSection 和 cellForItemsAt 都没有被第二次激活。

怎么了?打印语句显示数据正在传递(它们在拍摄照片后显示更新的数量)。由于没有调用两个 collectionView 函数,因此视图没有更新新数据。

编辑: 这是浮动面板代码

fpc = FloatingPanelController()
        fpc.delegate = self
        guard let contentVC = storyboard?.instantiateViewController(identifier: "fpc_secondContent") as? SecondContentViewController else {
            return
        }
        
        fpc.isRemovalInteractionEnabled = false
        fpc.set(contentViewController: contentVC)
        fpc.addPanel(toParent: self)

它本质上在 SecondTestViewController 的 viewDidLoad 内部。

有关其工作原理的更多信息:Visit this github

就 didSelectRowAt 函数而言,这里的代码太多了。 reviewDataController 是由结构数组组成的依赖注入。基本上所有发生的事情是当一个单元格被点击时,它会拉起相机并允许用户拍照,然后它将照片存储在 reviewDataController 内部的数组中,以及数组构成的结构中的一些其他属性.重要的部分是它应该将这些数据传递给浮动面板,然后浮动面板更新显示刚刚拍摄的照片的 collectionView。

解决方法

好像

let contentVC = SecondContentViewController() // this is a new instance
contentVC.reviewDataController = self.reviewDataController
contentVC.updateTheCollectionView()

您创建一个实例并将其添加到 SecondTestViewController ,但 passDataToContentVC 有另一个新实例,因此显示的实例没有更新

,

因为您将数据从 SecondTestViewController 传递到 SecondContentViewController,即向前而不是向后,所以您不需要委托或任何东西。

相反,您需要做的就是保留对 SecondContentViewController 的引用。尝试这样的事情:

class SecondTestViewController {
    var secondContentReference: SecondContentViewController? /// keep a reference here

    override func viewDidLoad() {
        super.viewDidLoad()

        let fpc = FloatingPanelController()
        fpc.delegate = self
        guard let contentVC = storyboard?.instantiateViewController(identifier: "fpc_secondContent") as? SecondContentViewController else {
            return
        }
        
        fpc.isRemovalInteractionEnabled = false
        fpc.set(contentViewController: contentVC)
        fpc.addPanel(toParent: self)

        self.secondContentReference = contentVC /// assign contentVC to the reference
    }
}

secondContentReference 保留对您的 SecondContentViewController 的引用。现在,在 passDataToContentVC 中,使用它而不是使用 let contentVC = SecondContentViewController() 创建一个新实例。

替换

func passDataToContentVC() {
    let contentVC = SecondContentViewController()
    contentVC.reviewDataController = self.reviewDataController
    contentVC.updateTheCollectionView()
}

...与

func passDataToContentVC() {
    secondContentReference?.reviewDataController = self.reviewDataController
    secondContentReference?.updateTheCollectionView()
}