cellForItemAt 在 Swift collectionView 中只调用一次
Posted
技术标签:
【中文标题】cellForItemAt 在 Swift collectionView 中只调用一次【英文标题】:cellForItemAt called only once in Swift collectionView 【发布时间】:2019-03-18 14:10:58 【问题描述】:如果我将流布局与 collectionView 一起使用,那么我的所有单元格对数据都是可见的。如果我使用自定义布局,则 cellForItemAt 仅针对索引 (0,0) 访问,并且相应地仅显示单个单元格。
我很困惑为什么 - 请帮忙!
下面的小例子:
视图控制器:
import UIKit
private let reuseIdentifier = "customCell"
class customCollectionViewController: UICollectionViewController
@IBOutlet var customCollectionView: UICollectionView!
let dwarfArray = ["dopey", "sneezy", "bashful", "grumpy", "doc", "happy", "sleepy"]
override func viewDidLoad()
super.viewDidLoad()
override func numberOfSections(in collectionView: UICollectionView) -> Int
return 1
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return dwarfArray.count
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! customCollectionViewCell
let cellContentsIndex = indexPath.row
if cellContentsIndex <= dwarfArray.count
cell.displayContent(name: dwarfArray[cellContentsIndex])
return cell
自定义单元格
import UIKit
class customCollectionViewCell: UICollectionViewCell
@IBOutlet weak var nameLabel: UILabel!
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
setup()
override init(frame: CGRect)
super.init(frame: frame)
public func displayContent(name: String)
nameLabel.text = name
func setup()
self.layer.borderWidth = 1.0
self.layer.borderColor = UIColor.black.cgColor
自定义布局 如果这不在这里 - 我可以看到我期望的所有单元格(尽管没有我喜欢的布局)。当我使用它时,我只看到一个单元格。
import UIKit
class customCollectionViewLayout: UICollectionViewLayout
let CELL_SIZE = 100.0
var cellAttrsDictionary = Dictionary<NSIndexPath, UICollectionViewLayoutAttributes>()
//define the size of the area the user can move around in within the collection view
var contentSize = CGSize.zero
var dataSourceDidUpdate = true
func collectionViewContentSize() -> CGSize
return self.contentSize
override func prepare()
if (collectionView?.numberOfItems(inSection: 0))! > 0
/// cycle through each item of the section
for item in 0...(collectionView?.numberOfItems(inSection: 0))!-1
/// build the collection attributes
let cellIndex = NSIndexPath(item: item, section: 0)
let xPos = Double(item)*CELL_SIZE
let yPos = 40.0
let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex as IndexPath)
cellAttributes.frame = CGRect(x: xPos, y:yPos, width: CELL_SIZE, height: CELL_SIZE)
// cellAttributes.frame = CGRect(x: xPos, y:yPos, width: CELL_WIDTH + 2*CELL_SPACING, height: CELL_HEIGHT)
cellAttributes.zIndex = 1
//save
cellAttrsDictionary[cellIndex] = cellAttributes
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
/// create array to hold all the elements in our current view
var attributesInRTect = [UICollectionViewLayoutAttributes]()
/// check each element to see if they should be returned
for cellAttributes in cellAttrsDictionary.values
if rect.intersects(cellAttributes.frame)
attributesInRTect.append(cellAttributes)
return attributesInRTect
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes?
return cellAttrsDictionary[indexPath as NSIndexPath]!
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool
return true
输出
【问题讨论】:
【参考方案1】:问题在于 contentSize 值
func collectionViewContentSize() -> CGSize
return self.contentSize
只需将func collectionViewContentSize()...
替换为以下内容:
func lastLayoutAttributes() -> UICollectionViewLayoutAttributes?
return cellAttrsDictionary.values.map $0 .sorted(by: $0.frame.maxX < $1.frame.maxX ).last
override var collectionViewContentSize: CGSize
guard let collectionView = collectionView else return .zero
guard collectionView.frame != .zero else return .zero
let width: CGFloat
let height: CGFloat = collectionView.frame.height
if let lastLayoutAttributes = lastLayoutAttributes()
width = lastLayoutAttributes.frame.maxX
else
width = 0
return CGSize(width: width, height: height)
你会看到不止一个单元格。
【讨论】:
以上是关于cellForItemAt 在 Swift collectionView 中只调用一次的主要内容,如果未能解决你的问题,请参考以下文章
CollectionView 方法 cellForItemAt indexPath: 未被调用 (Swift)
Xcode Swift UICollectionView:cellForItemAt IndexPath 未调用但 numberOfItemsInSection 调用
collectionView cellForItemAt 没有被调用
UICollectionViewController项插入动画Swift