iOS 13 个 CollectionView 委托方法未被调用

iOS 13 CollectionView delegate methods not getting called

我们的应用程序中有这段代码 运行 适用于所有版本的 iOS 除了 iOS 13。在 iOS 12 和下面的委托方法中像 cellForItemAt 和 willDisplayCell 一样被调用没有问题但是在 iOS 13 中只调用了 numberOfSections 而没有调用其他方法。

我已在 iOS 13 中查找可能导致此问题的 API 更改,但未找到任何更改。我是否遗漏了一些在 iOS 13.

中工作的东西

这是我的代码:

class PhotoBrowserView: UIView, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate {

    var photos: [PhotoURL] = [PhotoURL]() {
        didSet {
            photoCollectionView.reloadData()
        }
    }


    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return self.bounds.size
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath)
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {

        let cell = cell as! SimplePhotoCell
        cell.thumbnailButton.isUserInteractionEnabled = false
        cell.thumbnailPath = photos[indexPath.item].photoURL.absoluteString
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

        return photos.count
    }

}

我是这样称呼照片的:

class StoryView: ShowPageView, UIScrollViewDelegate {

    private let photosView: PhotoBrowserView = {
       return PhotoBrowserView()
    }()


    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)

        if self.traitCollection.horizontalSizeClass == .compact, viewModel.story.portraitPhotos.count > 0 {
            photosView.photos = viewModel.story.portraitPhotos
        } else {
            photosView.photos = viewModel.story.landscapePhotos
        }
    }
}

在以前的版本中 iOS traitCollectionDidChange 方法在将视图添加到视图层次结构时被调用,在 iOS 13 中,UIKit 在创建视图时设置视图的特征在将视图添加到视图层次结构之前。结果 traitCollectionDidChange 没有被调用,你的照片也没有设置。当您的照片未设置时,您的 collectionView 不会重新加载。

详情请参考Keith at UserYourLoaf。我将分享他的答案并添加一个我自己的答案。

正如所指出的,在 iOS 13 中,将视图添加到视图层次结构时不会调用 traitCollectionDidChange。它将在设备的后续旋转中被调用。在 iOS 13 之前,将视图添加到视图层次结构时会调用 traitCollectionDidChange。

iOS13 中的这一更改导致在任何旋转之前首次显示视图时,我的所有控件都左对齐。它们在 iOS 13.

之前居中

通过以下方法之一修复您的代码:

  1. 在 viewDidLoad 中调用您的特征设置方法(基本上将 traitCollectionDidChange 主体的相关部分复制到一个新方法,然后您可以从 viewDidLoad 和 traitCollectionDidChange 中调用。

  2. 按照 Apple 的指导将特征设置调用添加到以下方法之一:

    UIViewController.viewWillLayoutSubviews()

    UIView.layoutSubviews()

    UIViewController.viewDidLayoutSubviews()

  3. 作为 viewDidLoad 方法的最后一行,调用您现有的传递 nil 的方法,如下所示:

    viewDidLoad() { . . . traitCollectionDidChange(无) }

考虑记录为什么您偏离 iOS 版本。否则,有人碰巧删除了您在处理旧 iOS 版本时显得多余的添加。您可能需要考虑为此更改创建技术债,类似于:

// TODO: When I quit supporting pre iOS 13, this conditional can be removed
if #available(iOS 13, *) {
   <whatever solution you chose above>
}