Ios Swift:集合视图的惰性填充
我正在学习Swift,并编写一个小应用程序,用图像显示收藏视图。它不工作,而且图像永远不会显示。我在Ios Swift:集合视图的惰性填充,ios,swift,uiimageview,uicollectionview,lazy-loading,Ios,Swift,Uiimageview,Uicollectionview,Lazy Loading,我正在学习Swift,并编写一个小应用程序,用图像显示收藏视图。它不工作,而且图像永远不会显示。我在collectionView cellForItemAtIndexPath中看到了奇怪的行为:当我惰性地加载要在单元格中显示的图像并第二次调用collectionView.dequeueReusableCellWithReuseIdentifier()时,它返回一个不同的单元格。这发生在我滚动集合视图之前,所以单元重用应该不是问题。这是我的密码: func collectionView(c
collectionView cellForItemAtIndexPath
中看到了奇怪的行为:当我惰性地加载要在单元格中显示的图像并第二次调用collectionView.dequeueReusableCellWithReuseIdentifier()
时,它返回一个不同的单元格。这发生在我滚动集合视图之前,所以单元重用应该不是问题。这是我的密码:
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let reuseIdentifier = "CollectionCell"
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath:indexPath) as! ImageCollectionCell
cell.imageView.contentMode = UIViewContentMode.ScaleAspectFill
cell.countLabel.text = "\(indexPath.row+1)"
let imageIndex = XKCDClient.sharedInstance.totalCount - indexPath.row - 1
println("loading image # \(imageIndex)")
XKCDClient.sharedInstance.loadComic(imageIndex, completion: { (comicData) -> Void in
if let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath:indexPath) as? ImageCollectionCell {
println("got image # \(imageIndex)")
cell.imageView.backgroundColor = UIColor.blackColor()
if(comicData.image != nil) {
// cell.imageView.image = comicData.image // (1)
cell.imageView.image = UIImage(named: "placeholder") // (2)
cell.setNeedsDisplay()
}
}
else {
println("cell \(imageIndex) already reused");
}
})
return cell
}
发生了什么:
- 为每个索引路径调用回调块
对象被正确地传递到回调块中UIImage
- 对回调内单元格的任何更改似乎都不会产生任何影响(包括设置背景色)
- 回调内部的
返回的单元格与方法开头返回的单元格不同。这似乎是问题的根源collectionView.dequeueReusableCellWithReuseIdentifier()
有人能解释一下这里发生了什么吗?不要在回调闭包中再次调用
dequeuReusableCellWithReuseIdentifier
,而是调用cellForItemAtIndexPath
。注意:在单元格中设置图像时,必须在主线程中执行:
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let reuseIdentifier = "CollectionCell"
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! ImageCollectionCell
cell.imageView.image = nil
cell.imageView.contentMode = UIViewContentMode.ScaleAspectFill
cell.countLabel.text = "\(indexPath.row+1)"
let imageIndex = XKCDClient.sharedInstance.totalCount - indexPath.row - 1
XKCDClient.sharedInstance.loadComic(imageIndex, completion: { (comicData) -> Void in
if let img = comicData.image {
// Note: Set image in the main thread
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = img
}
} else {
println("No image in comicData")
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = nil
}
}
})
return cell
}
不要在回调闭包中再次调用
dequeuReusableCellWithReuseIdentifier
,而是调用cellForItemAtIndexPath
。注意:在单元格中设置图像时,必须在主线程中执行:
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let reuseIdentifier = "CollectionCell"
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! ImageCollectionCell
cell.imageView.image = nil
cell.imageView.contentMode = UIViewContentMode.ScaleAspectFill
cell.countLabel.text = "\(indexPath.row+1)"
let imageIndex = XKCDClient.sharedInstance.totalCount - indexPath.row - 1
XKCDClient.sharedInstance.loadComic(imageIndex, completion: { (comicData) -> Void in
if let img = comicData.image {
// Note: Set image in the main thread
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = img
}
} else {
println("No image in comicData")
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = nil
}
}
})
return cell
}
非常感谢。这确实会导致图像显示在单元格中,但此代码也有一个问题:它通常在单元格回收后显示图像。这意味着图像显示在错误的单元格中。这就是我在回调中第二次得到单元格的原因。是的,您可以使用一个允许在重用单元格时使回调无效的抽象(例如),也可以在闭包内调用tableView.CellForRowatineXpath。你不应该让一个新的牢房排队。好的,我知道我的错误是什么。在回调中,我再次将单元格从队列中移出,而不是调用
cellForItemAtIndexPath
。我打赌就是这样。如果你想用这个建议更新你的答案,我会接受。好的,更新答案。我一直提到你必须在主线程中设置图像。干杯,谢谢。顺便说一句,据我所知,回调是在主线程上执行的,没有任何额外的代码(它是在方法调用所在的线程上执行的,对于cellForItemAtIndexPath
,它是主线程)。谢谢。这确实会导致图像显示在单元格中,但此代码也有一个问题:它通常在单元格回收后显示图像。这意味着图像显示在错误的单元格中。这就是我在回调中第二次得到单元格的原因。是的,您可以使用一个允许在重用单元格时使回调无效的抽象(例如),也可以在闭包内调用tableView.CellForRowatineXpath。你不应该让一个新的牢房排队。好的,我知道我的错误是什么。在回调中,我再次将单元格从队列中移出,而不是调用cellForItemAtIndexPath
。我打赌就是这样。如果你想用这个建议更新你的答案,我会接受。好的,更新答案。我一直提到你必须在主线程中设置图像。干杯,谢谢。顺便说一句,据我所知,回调是在主线程上执行的,没有任何额外的代码(它是在方法调用所在的线程上执行的,对于cellForItemAtIndexPath
,它是主线程)。