Ios UIImageView最初不在UITableViewCell中显示图像
我有一个从服务加载图像的Ios UIImageView最初不在UITableViewCell中显示图像,ios,swift,uitableview,uiimageview,Ios,Swift,Uitableview,Uiimageview,我有一个从服务加载图像的UITableView。它通过NSURLSession.sharedSession().dataTaskWithURL获取URL并下载图像: NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, _, error) -> Void in guard
UITableView
。它通过NSURLSession.sharedSession().dataTaskWithURL获取URL并下载图像:
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
内容模式为方面匹配
可见单元格的UIImageView
最初显示为空(无图像),即使我已确认设置了图像。直到单元格在屏幕上/屏幕上滚动,单元格才会重新绘制(?)并显示图像
这似乎是个时间问题,但我想不出来。设置映像后,我尝试在dispatch\u async
块中调用以下所有内容:
self.pictureView.setNeedsDisplay()
self.pictureView.setNeedsUpdateConstraints()
self.pictureView.setNeedsLayout()
self.pictureView.reloadInputViews()
这些都不能解决问题。是什么原因导致此图像仅在单元格滚出/滚入视图后显示
编辑:
可能需要注意的是,这是在nib和相关类中发生的。加载nib后,我开始下载。我想知道nib是否进行了布局,当我的图像被下载并设置在UIImageView
上时,布局过程已经完成。然后,通过将单元格(包含nib)移离/移到屏幕上,单元格再次执行布局,所有内容都正确显示。只是一个猜测,我仍然坚持这一点
编辑2:
进一步澄清该过程:
1) MyUIViewController
包含一个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
请注意,在PostView上调用awakeFromNib()
后会发生这种情况
5) PostView上的post
属性有一个didSet
observer,它根据post
对象(上面的代码)中的URL启动图像下载。图像被下载并设置在名为pictureView
的UIImageView
上
编辑3:
以下是表格视图(uxCELLFORROWATINDEXPATH:)
的代码:
编辑4:
我发现,如果我通过在nib中预先设置占位符图像来“初始化”UIImageView
,然后将图像加载到该UIImageView
,图像将显示在占位符的高度。当我将该单元格拉离屏幕,然后再次打开时,UIImageView
将使用nib中的约束设置以正确的大小绘制图像
因此,UIImageView
的约束和大小似乎在图像加载时已经设置好,将其从屏幕上/从屏幕上拉出会导致某种类型的重画,从而正确调整图像的大小。如果我能以编程方式触发该重画,它会有所帮助,但请参阅上面我已经尝试过的内容
编辑6:
在这里,它正在发挥作用。注意,我在nib中设置了一个占位符图像。这似乎会导致图像在最初加载时显示,但显示在占位符的尺寸上。当屏幕正确显示时,在屏幕外短暂滚动会导致调整大小。
编辑7:
我在我的应用程序的其他地方使用PostView nib没有问题。加载时,图像大小正确。问题似乎只出现在nib嵌入到UITableViewCell
中时
编辑8:
我在我的UIViewController
的viewDidLoad中找到了此问题的根本原因:
tableView.estimatedRowHeight = 500
tableView.rowHeight = UITableViewAutomaticDimension
使用“自动标注”会导致初始行高度不正确。由于某些原因,将单元格向外/向内滚动将正确重新计算行高,并且图像显示在正确的高度。删除此代码将显示图像,但行高度不会从自动高度计算中受益。自动计算行高并避免此问题的最佳方法是什么?您可以尝试此扩展:
extension UIImageView {
func downloadedFrom(link link:String, contentMode mode: UIViewContentMode) {
guard
let url = NSURL(string: link)
else {return}
contentMode = mode
NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, response, error) -> Void in
guard
let httpURLResponse = response as? NSHTTPURLResponse where httpURLResponse.statusCode == 200,
let mimeType = response?.MIMEType where mimeType.hasPrefix("image"),
let data = data where error == nil,
let image = UIImage(data: data)
else { return }
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.image = image
}
}).resume()
}
}
然后你可以把这条线放在任何你想放的地方
cell.cellPhoto.downloadedFrom(link: "customImageUrl", contentMode: .ScaleAspectFit) //Try changing contentMode
下载完成后,需要重新加载tableview数据。尝试调用self.tableview.reloadData()
insidedispatch\u async
block
另外,如果您想从URL异步下载图像,我建议您使用您看到了吗?这段视频可能会让你对你的问题有更多的了解
在WWDC会话中,他们使用self.tableView.estimatedRowHeight=100.0代码>您已完成的操作✅ 然后他们说你不需要任何来自表视图控制器的虚拟原型单元
然后问题是,当序列图像板加载表视图时,它会将rowHeight
属性设置为来自xib/interface builder的值。要使用自动调整单元格大小,您需要设置estimatedRowHeight
,并将rowHeight
保留为默认值-UITableViewAutomaticDimension
。(您已完成的操作)✅
self.tableView.rowHeight=UITableViewAutomaticDimension
⚠️新的问题是,第一个单元格在获得真正的行高之前加载。诀窍可能是在视图显示时强制重新加载表
[super viewDidAppear:animated]
[self.tableView reloadData]
如果这不起作用,那么可能是您无意中在某个内容上设置了显式的contentWidth/Height,导致其大小不正确❓❓ 在查看了回复者的编辑过程(目前为8次)和更新之后,您似乎在init方法中遇到了导致错误的相同错误
应将注册nib的正确轨道归功于Prcela,但下面提供了一个更优雅的解决方案:
在nib文件中创建自定义表视图单元格的最简单方法(从iOS 5.0开始提供)是使用reg
[super viewDidAppear:animated]
[self.tableView reloadData]
[self.tableView registerNib:[UINib nibWithNibName:@"CueTableCell" bundle:nil] forCellReuseIdentifier:@"CueTableCell"];
CueTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CueTableCell"];
// setup cell
return cell;