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.
之前居中
通过以下方法之一修复您的代码:
在 viewDidLoad 中调用您的特征设置方法(基本上将 traitCollectionDidChange 主体的相关部分复制到一个新方法,然后您可以从 viewDidLoad 和 traitCollectionDidChange 中调用。
按照 Apple 的指导将特征设置调用添加到以下方法之一:
UIViewController.viewWillLayoutSubviews()
UIView.layoutSubviews()
UIViewController.viewDidLayoutSubviews()
作为 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>
}
我们的应用程序中有这段代码 运行 适用于所有版本的 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.
之前居中通过以下方法之一修复您的代码:
在 viewDidLoad 中调用您的特征设置方法(基本上将 traitCollectionDidChange 主体的相关部分复制到一个新方法,然后您可以从 viewDidLoad 和 traitCollectionDidChange 中调用。
按照 Apple 的指导将特征设置调用添加到以下方法之一:
UIViewController.viewWillLayoutSubviews()
UIView.layoutSubviews()
UIViewController.viewDidLayoutSubviews()
作为 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>
}