UICollectionView获取itemSize始终为默认50x50但显示正常如何解决?
问题原因
- 你实现了
UICollectionViewDelegateFlowLayout的collectionView(_:layout:sizeForItemAt:)动态尺寸代理方法,此时系统渲染Cell时会优先读取该方法的返回值,不会修改UICollectionViewFlowLayout的itemSize默认属性,所以你直接打印该属性永远会拿到初始化的默认值50x50。 - 代码存在语法错误:
let dimension = self.view.bounds/3写法不合法,bounds为CGRect类型,需要取宽度属性计算:self.view.bounds.width / 3,否则会触发编译报错。
解决方案
方法1:复用计算逻辑(无重复代码)
把Cell尺寸计算逻辑封装为独立方法,代理方法和cellForItemAt中同时调用即可:
// 封装尺寸计算逻辑 private func getItemSize() -> CGSize { let dimension = view.bounds.width / 3 return CGSize(width: dimension, height: dimension) } // 代理方法调用 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return getItemSize() } // cellForItemAt中调用拿尺寸 override final func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cellSize = getItemSize() print("Cell Size: ", cellSize) // 后续业务逻辑 // ... }
方法2:直接修改FlowLayout的itemSize(无需实现代理方法)
如果所有Cell尺寸统一,不需要按indexPath区分,可以直接在布局更新时修改FlowLayout的itemSize属性,无需实现sizeForItemAt代理:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() guard let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout else { return } let dimension = view.bounds.width / 3 let targetSize = CGSize(width: dimension, height: dimension) // 仅在尺寸变化时更新,避免重复触发布局 if flowLayout.itemSize != targetSize { flowLayout.itemSize = targetSize collectionView.reloadData() } } // 此时直接在cellForItemAt中打印itemSize就是正确值 override final func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cellSize = (collectionViewLayout as! UICollectionViewFlowLayout).itemSize print("Cell Size: ", cellSize) // 后续业务逻辑 // ... }
如果有横竖屏切换需求,上述两种方案都可以自动适配新的尺寸,无需额外处理。
内容的提问来源于stack exchange,提问作者Gizmodo
相关产品推荐
相关产品推荐

