我有一个带有动态单元格的tableView。每个单元格都有一个imageView和一个textLabel。我正在和Alamofire&顺便说一下AlamofireImage。 我的问题是,第一个单元格(如果视图确实出现,您会看到)不会显示图像。但如果我向下滚动,我会看到其他细胞的图像。如果再次向上滚动,第一个单元格的图像也会出现。
首先,我在viewDidLoad方法中下载用户数据。完成此操作后,我使用tableView.reloadData()更新tableview。
override func viewDidLoad() {
super.viewDidLoad()
MYRequest_getUsers(//...
,
success: {response -> Void in
self.users = response
dispatch_async(dispatch_get_main_queue(),{
self.tableView.reloadData()
})
},
failure: {NSError -> Void in
debugPrint(NSError)
})
}
TableView统计用户并重新加载。
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users?.count ?? 0
}
在tableView_cellForRowAtIndexPath方法中,我使用用户数据填充单元格。
let cell = tableView.dequeueReusableCellWithIdentifier(self.identifier) as! UserCell
cell.userNameLabel.tag = indexPath.row
let rowData: User = self.users?[cell.userNameLabel.tag] as User!
cell.userNameLabel.text = rowData.getName()
let avatarURL = rowData.getAvatarURL() ?? ""
cell.userImageView.af_setImageWithURL(imgURL, placeholderImage: placeholderImage)
return cell
我的想法是,在加载用户数据后,tableView开始绘制自己并放置名称(因为它已经在userData中)。但是图像是异步下载的(我猜),所以它们在延迟一段时间之后来自后端,并且已经绘制了tableView。上下滚动后,我看到了它们。
我想打开屏幕而不上下滚动。 Tableview应在加载后自动设置图像。所以我想做一个回调并使用而不是
cell.userImageView.af_setImageWithURL(imgURL, placeholderImage: placeholderImage)
此
Alamofire.request(.GET, avatarURL)
.responseImage { response in
cell.userImageView.image = response.2.value
dispatch_async(dispatch_get_main_queue(), { () -> Void in
tableView.setNeedsLayout()
})
}
但是没有任何改变......我已经尝试了很多并且看起来类似的问题但是无法解决它...我希望你能给我一些提示或更好的解决方案! :)
提前致谢
答案 0 :(得分:5)
我想通过发布步骤(在这种情况下遵循的最佳做法)给你一个方向:
第1步:只要您有来自服务器的图片网址,就可以在后台获取图片。我更喜欢在操作队列中这样做,我同时下载多个图像。您可以编写一个辅助类,它使用完成块并实现NSOperation
/ NSOperationQueue
。
第2步:在下载图片时,为了用户的眼睛,在图片视图上加载加载图层。您可以在cellForRowAtIndexPath:
。
第3步:图像可用后,将它们缓存在文件系统中。这是为了避免任何滚动突然行为。
第4步:图像可用后,请调用完成块。
步骤5:在完成块中,在主线程上重新加载表。确保您的cellForRowAtIndexPath:
首先检查缓存中的图像(如果有),如果不存在则显示加载覆盖,如果图像提取正在进行中。如果图像在缓存中不可用且下载也未进行,则显示一些默认图像。
答案 1 :(得分:2)
这个问题已有几年历史了,但也许这个答案对于有类似问题的其他人有用,就像我之前找到正确的解决方案一样。
由于图像是异步加载的,如果我们没有为UIIMageView提供固定的高度,我们必须在下载完成时强制更新单元格。这是因为单元更新(即AutoLayout约束重新计算)仅在initialParts()
方法之后自动完成,该方法在第一次显示单元格时调用,或者在滚动表格以显示其他单元格时。在这两种情况下,cellForRowAt
方法可能尚未下载图像,因此只显示占位符,因为它们的尺寸目前尚不清楚。
要强制更新单元格,我们需要使用af_setImage()
和beginUpdates()
方法,将它们放在endUpdates()
的完成处理程序中。这样,每次下载完成后,单元格都会更新。
但是,为了避免循环,在调用.af_setImage()
/ beginUpdates()
之前,我们必须检查我们之前是否已经更新了单元格,因为通过调用这些方法,endUpdates()
方法再次调用,因此cellForRowAt
及其完成闭包,其中包含af_setImage()
/ beginUpdates()
。
这意味着我们必须仅在下载完成时更新单元格,而不是在成像被兑现时更新单元格(因为,如果它被兑现,则意味着我们已经更新了单元格)。这可以通过检查完成处理程序的响应来完成:如果它不是nil,则图像刚刚下拉,如果它是nil,则图像被兑现。
作为附带好处,细胞高度将自动调整(记得在endUpdates()
方法中放置tableView.estimatedRowHeight = 400
和tableView.rowHeight = UITableViewAutomaticDimension
)
最后,这是代码:
viewDidLoad()
那是所有人! ; - )
答案 2 :(得分:0)
实现这一目标很少。