【发布时间】:2016-10-29 18:05:08
【问题描述】:
我有一个从服务加载图像的UITableView。它获取 URL 并使用 NSURLSession.sharedSession().dataTaskWithURL 下载图像:
NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, _, error) -> Void in
guard
let data = data where error == nil,
let image = UIImage(data: data)
else {
print(error?.localizedDescription)
return
}
dispatch_async(dispatch_get_main_queue()) {
[unowned self] in
self.pictureView.image = image
self.pictureView.layoutIfNeeded()
}
}).resume()
UIImageView 是故事板场景的出口。 UIImageView 内容模式是 Aspect Fit。
可见单元格的UIImageView 最初显示为空(无图像),即使我已确认已设置图像。直到单元格在屏幕上滚动关闭/滚动,单元格才会重绘(?)并显示图像。
所以这似乎是某种时间问题,但我无法弄清楚。设置图像后,我尝试在 dispatch_async 块中调用以下所有内容:
self.pictureView.setNeedsDisplay()
self.pictureView.setNeedsUpdateConstraints()
self.pictureView.setNeedsLayout()
self.pictureView.reloadInputViews()
这些都不能解决问题。是什么导致此图像仅在单元格滚动出/进入视图后显示?
编辑:
值得注意的是,这是发生在 nib 和相关类中的。笔尖已加载,然后我开始下载。我想知道笔尖是否会自行布局,当我的图像被下载并设置在UIImageView 上时,布局通道已经完成。然后通过在屏幕上移动单元格(包含笔尖),单元格再次执行布局并正确显示所有内容。只是一个猜测,我仍然坚持这一点。
编辑 2: 进一步澄清流程:
1) 我的UIViewController 包含一个UITableView。
2) 这个UITableView 从一个名为 PostCell 的自定义 UITableViewCell 类中加载单元格。
3) PostCell 的全部内容是从名为 PostView 的 nib 加载的单个视图(带有 PostView 类)。该负载发生在 PostCell 中的 init:style:reuseIdentifier 期间:
postView = NSBundle.mainBundle().loadNibNamed("PostView", owner: self, options: nil).first as? PostView
4) 然后我在postView 上设置一个 Post 对象:
postView.post = Post
请注意,这发生在 awakeFromNib() 在 PostView 上调用之后。
5) PostView 上的post 属性有一个didSet 观察者,它根据post 对象(上面的代码)中的URL 启动图像下载。图像被下载并设置在名为pictureView 的UIImageView 上。
编辑 3:
这是tableView(_:cellForRowAtIndexPath:)的代码:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(postCellIdentifier) as? PostCell
if cell == nil {
cell = PostCell()
}
if let postCell = cell,
let postArray = postArray,
let post = postArray[indexPath.row] {
postCell.post = post
return postCell
}
// This section is hit during a refresh.
let emptyCell = UITableViewCell()
emptyCell.contentView.backgroundColor = .whiteColor()
return emptyCell
}
编辑 4:
我发现如果我通过在笔尖中预先设置一个占位符图像来“填充”UIImageView,然后将我的图像加载到该UIImageView,图像将显示在占位符的高度。当我将该单元格拉出屏幕然后再次打开时,UIImageView 将使用笔尖中的约束设置以正确的大小绘制图像。
因此,UIImageView 的约束和大小似乎在图像加载时已设置,并且将其从屏幕上拉下/拉上会导致某种类型的重绘,从而正确调整图像的大小。如果我可以以编程方式触发重绘会有所帮助,但请参阅上面的内容了解我已经尝试过的内容。
编辑 6:
它正在发挥作用。请注意,我在笔尖中设置了一个占位符图像。这似乎导致图像在最初加载时显示,但在占位符的尺寸上。当它正确显示时,将其短暂滚动到屏幕外会导致调整大小。
编辑 7:
我在我的应用程序的其他地方使用 PostView nib 没有问题。当它加载图像大小正确。问题似乎只出现在 nib 嵌入 UITableViewCell 中。
编辑 8:
我找到了这个问题的根本原因,在我的UIViewController 的 viewDidLoad 中调用:
tableView.estimatedRowHeight = 500
tableView.rowHeight = UITableViewAutomaticDimension
使用自动标注会导致初始行高不正确。出于某种原因,将单元格滚动出/进入视图将正确重新计算行高,并且图像以正确的高度显示。删除此代码将显示图像,但行高不会从自动高度计算中受益。自动计算行高并避免此问题的最佳方法是什么?
【问题讨论】:
-
你什么时候调用 dataTaskWithURL ?
-
@TejaNandamuri 在
tableView:cellForRowAtIndexPath中调用。我用dequeueReusableCellWithIdentifier获取自定义UITableViewCell。然后我在那个单元格上设置一个对象,它有一个didSet来获取图像。 -
self.pictureView.image = image或cell.pictureView.image = image? -
张贴您的
tableView:cellForRowAtIndexPath:了解更多详情,请。 -
您是否尝试过:
tableView.beginUpdates(); tableView.endUpdates;在异步块中?
标签: ios swift uitableview uiimageview