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()
这些都没有解决问题.导致此图像仅在单元格滚出/进入视图后才显示?
编辑:
可能重要的是要注意,这是在一个笔尖和相关的类中进行的.笔尖加载,然后我开始下载.我想知道笔尖是否放在自己的位置,当我的图像下载并设置在UIImageView上时,布局传递已经完成.然后通过移动单元格(包含笔尖)关闭/屏幕上,单元格再次执行布局,并且所有内容都正确显示.只是一个猜测,我仍然坚持这个.
编辑2:
进一步澄清过程:
1)我的UIViewController包含一个UITableView.
2)这个UITableView从一个称为PostCell的自定义UITableViewCell类加载单元.
3)PostCell的全部内容是从名为PostView的nib(使用PostView类)加载的单个视图.在init期间会发生这种负载:PostCell中的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观察者,它基于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没有问题.加载图像的大小正确.这个问题似乎表现在自己的嵌套在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,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