我正在使用 Alamofire 构建类似 pinterest 的布局。
然后我关注了uicollectionview-custom-layout-tutorial-pinterest在这里建立一个类似 pinterest 的布局。当我想用异步下载的照片实现它时,它失败了。
Assertion failure in -[UICollectionViewData layoutAttributesForItemAtIndexPath:]
Alamofire.request(Unicooo.Router.ReadPostList("",["act_id": self.actId, "page": self.currentPage])).validate().responseJSON {
response in
switch response.result {
case .Success:
let JSON = response.result.value
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
let photoInfos = ((JSON as! NSDictionary).valueForKey("results") as! [NSDictionary]).map {
PostPhotoInfo(id: ($0["id"] as! Int), title: ($0["post_title"] as! String)...)
}
let lastItem = self.postPhotos.count
self.postPhotos.addObjectsFromArray(photoInfos)
let indexPaths = (lastItem..<self.postPhotos.count).map { NSIndexPath(forItem: $0, inSection: 0)}
dispatch_async(dispatch_get_main_queue()) {
self.collectionView!.insertItemsAtIndexPaths(indexPaths) // Thread 1: breakpoint 1.1.
}
}
当我将 Main.storyboard Collection View 布局设置为 Flow 时效果很好,但是当我像这样使用自定义流时:
private var cache = Dictionary<NSIndexPath, UICollectionViewLayoutAttributes>() //I change cache to Dictionary
override func prepareLayout() {
if cache.isEmpty {
let columnWidth = contentWidth / CGFloat(numberOfColumns)
var xOffset = [CGFloat]()
for column in 0 ..< numberOfColumns {
xOffset.append(CGFloat(column) * columnWidth )
}
var column = 0
var yOffset = [CGFloat](count: numberOfColumns, repeatedValue: 0)
for item in 0 ..< collectionView!.numberOfItemsInSection(0) {
let indexPath = NSIndexPath(forItem: item, inSection: 0)
let width = columnWidth - cellPadding * 2
let photoHeight = delegate.collectionView(collectionView!, heightForPhotoAtIndexPath: indexPath,
withWidth:width)
let annotationHeight = delegate.collectionView(collectionView!,
heightForAnnotationAtIndexPath: indexPath, withWidth: width)
let height = cellPadding + photoHeight + annotationHeight + cellPadding
let frame = CGRect(x: xOffset[column], y: yOffset[column], width: columnWidth, height: height)
insetFrame = CGRectInset(frame, cellPadding, cellPadding)
let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
attributes.frame = insetFrame!
cache[indexPath] = attributes //I change this line
contentHeight = max(contentHeight, CGRectGetMaxY(frame))
yOffset[column] = yOffset[column] + height
column = column >= (numberOfColumns - 1) ? 0 : ++column
}
}
}
override func collectionViewContentSize() -> CGSize {
return CGSize(width: contentWidth, height: contentHeight)
}
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var layoutAttributes = [UICollectionViewLayoutAttributes]()
for (_, attributes) in cache {
if CGRectIntersectsRect(attributes.frame, rect) {
layoutAttributes.append(attributes)
}
}
return layoutAttributes
}
当我在 google 中搜索有关 Collection View 的所有内容时:我尝试添加此方法:
override func layoutAttributesForItemAtIndexPath(_ indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
let attributes = cache[indexPath]
return attributes
}
但是还是不行。我想这可能与layoutAttributesForItemAtIndexPath没有返回更正属性有关。
感谢您的任何想法。
最佳答案
有点晚了,但我遇到了同样的问题。
您还需要覆盖 invalidateLayout
方法。
override func invalidateLayout() {
cache.removeAll()
super.invalidateLayout()
}
然后您需要在调用 insertItemsAtIndexPaths
之前调用 invalidateLayout 方法
您需要清除缓存,因为只有在缓存为空时才会调用 prepareLayout
方法中的逻辑。由于布局已经准备好并且缓存已填充,因此不会计算新的布局属性并将其存储在缓存中。
关于ios - 在 Collection View 中异步追加项目失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35932706/