当我将新单元格添加到集合视图时,我不断收到布局错误
Posted
技术标签:
【中文标题】当我将新单元格添加到集合视图时,我不断收到布局错误【英文标题】:I keep on receiving a layout error when I add a new cell to a collection view 【发布时间】:2018-01-25 16:50:02 【问题描述】:我正在尝试将数据从一个视图控制器添加到集合视图控制器,该控制器将元素添加到数据源数组,然后将单元格添加到集合视图。
prepareforsegue
之前的ViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if segue.identifier == "unwindToCollectionView"
let CVC = segue.destination as! CollectionViewController
if let image = image
CVC.images.insert(imagePost(image:image), at: 0)
print("Image is not nil")
let index = IndexPath(item: 0, section: 0)
//CVC.collectionView?.reloadData()
CVC.collectionView?.collectionViewLayout.invalidateLayout()
CVC.collectionView?.layoutIfNeeded()
CVC.collectionView?.insertItems(at: [index])
//CVC.collectionView?.reloadItems(at: [index])
print("In prepare for segue: \(CVC.images.count)")
collectionViewController
cellForItemAt
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
// Configure the cell
cell.cellImageView.image = images[indexPath.row].image
cell.cellImageView.clipsToBounds = true
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
layout.itemSize = CGSize(width: (UIScreen.main.bounds.width-1)/2, height: (UIScreen.main.bounds.width-1)/2)
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
collectionView.collectionViewLayout = layout
cell.cellImageView.layer.cornerRadius = CGFloat((cell.cellImageView.frame.width)/2)
return cell
收到错误:
2018-01-25 11:43:16.228902-0500 CAR+CV(1.0)Server[4182:1181750] *** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无法设置布局 [] [;层 = ;内容偏移:0,-88;内容大小:375, 573; adjustedContentInset: 88, 0, 83, 0> 集合视图布局: ] 在更新期间。
【问题讨论】:
您为什么在prepareForSegue
中调用invalidateLayout
、layoutIfNeeded
和insertItems
?另外我认为您不应该在cellForItemAtIndexPath
中设置UICollectionViewFlowLayout
……为什么不使用UICollectionViewDelegateFlowLayout
协议中的方法?
@shim 如果不在prepareForSegue
中,应该在哪里调用insertItems
当我尝试删除它并在collectionViewController
的viewDidLoad
内调用它时,我收到了有关索引的错误。
也许你误解了insertItems
的目的。您只需要设置cellForItemAt
和numberOfItemsInSection
并且集合视图会自行处理插入项目。 insertItems
主要用于当您需要显示正在添加的新项目时 - 并且必须在集合视图的数据源中进行相应的更改。
@shim 我在 segue 之后传递了一个带有添加项的数组。当我不在prepareForSegue
中调用insertItems
时,collectionView 中不会生成新单元格
【参考方案1】:
这样做的方法非常错误......
首先,将您的collectionViewLayout
设置为viewDidLoad()
接下来,在prepareForSegue
中,您要修改集合视图的数据,而不是集合视图本身。
所以...
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if segue.identifier == "unwindToCollectionView"
let CVC = segue.destination as! CollectionViewController
if let image = image
// add the image to the CollectionViewController's data
CVC.images.insert(imagePost(image:image), at: 0)
print("Image is not nil")
print("In prepare for segue: \(CVC.images.count)")
那么,您的收藏视图的cellForItemAt
就是:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
// Configure the cell
cell.cellImageView.image = images[indexPath.row].image
// don't do this here...
// cell.cellImageView.clipsToBounds = true
// cell.cellImageView.layer.cornerRadius = CGFloat((cell.cellImageView.frame.width)/2)
return cell
编辑: 作为旁注,设置.cornerRadius
也不应该在cellForItemAt
中完成,因为单元格还不会被布局。更好地继承 UIImageView
并在 layoutSubviews()
中设置 .cornerRadius
编辑 2:
class RoundImageView: UIImageView
override func layoutSubviews()
super.layoutSubviews()
self.clipsToBounds = true
self.layer.cornerRadius = self.frame.width / 2.0
只需将您当前的 UIImageView
的 Class 设置为 RoundImageView
。
“我在哪里调用 insertItems(at:[index])”
您不需要这样做。当您的 segue 移动到视图控制器时,您的集合视图将重新加载,并且您刚刚插入 images
数组的图像将成为第一个单元格。我注意到您的 segue 标识符是 "unwindToCollectionView"
- 因此,如果您的集合视图不自动重新加载,请将其添加到持有集合视图的 VC:
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
collectionView.reloadData()
【讨论】:
感谢您的回复,非常有帮助。除了更新 collectionViewController 中的数组外,我已将布局移至viewDidLoad
并从 prepareForSegue
中删除了所有内容。但是我在哪里调用insertItems(at:[index])
以便collectionView
为数组中的新元素添加一个新单元格。什么不会在cellForItemAt
中设置cornerRadius
看起来我必须覆盖layoutSubviews
@user372382 - 请参阅我的回答中的 Edit 2。
感谢您的编辑,现在代码可以正常工作,这对您很有帮助。是否可以使用collectionView.reloadItems(at: [IndexPath])
而不是collectionView.reloadData()
?
从逻辑上考虑...假设您的集合视图如下所示:A | B | C | D
(您的 images
数组)...您正在将 Z
插入数组中的位置 0
.如果您只使用.reloadItems(at: [IndexPath])
,您的收藏视图将如下所示:Z | B | C | D
。那是你想要的目标吗?还是您希望结果为Z | A | B | C | D
?我怀疑是后者,在这种情况下你想要.reloadData()
。以上是关于当我将新单元格添加到集合视图时,我不断收到布局错误的主要内容,如果未能解决你的问题,请参考以下文章