异步加载图像不断导致图像闪烁?
Posted
技术标签:
【中文标题】异步加载图像不断导致图像闪烁?【英文标题】:Asynchronously Loading Image constantly causes image to flicker? 【发布时间】:2015-05-20 18:17:38 【问题描述】:每个UITableViewCell
都有一个标题视图。在这个标题视图中,我通过 Facebook API 中的异步函数加载了个人的图片。但是,由于函数是异步的,我相信该函数被一遍又一遍地调用多次,导致图像不断闪烁。我想解决这个问题的方法是首先将viewDidLoad
中的图像加载到一个数组中,然后在UITableViewCell
的标题视图中显示数组内容。但是,由于该函数的异步性质,我无法实现这一点:我似乎无法抓取每张照片,然后继续执行我的程序。这是我的尝试:
//Function to get a user's profile picture
func getProfilePicture(completion: (result: Bool, image: UIImage?) -> Void)
// Get user profile pic
let url = NSURL(string: "https://graph.facebook.com/1234567890/picture?type=large")
let urlRequest = NSURLRequest(URL: url!)
//Asynchronous request to display image
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue()) (response:NSURLResponse!, data:NSData!, error:NSError!) -> Void in
if error != nil
println("Error: \(error)")
// Display the image
let image = UIImage(data: data)
if(image != nil)
completion(result: true, image: image)
override func viewDidLoad()
self.getProfilePicture (result, image) -> Void in
if(result == true)
println("Loading Photo")
self.creatorImages.append(image!)
else
println("False")
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
//Show section header cell with image
var cellIdentifier = "SectionHeaderCell"
var headerView = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! SectionHeaderCell
headerView.headerImage.image = self.creatorImages[section]
headerView.headerImage.clipsToBounds = true
headerView.headerImage.layer.cornerRadius = headerView.headerImage.frame.size.width / 2
return headerView
如上面的程序所示,我创建的名为self.creatorImages
的全局数组包含我从 Facebook API 获取的图像数组,它始终是空的,我需要“等待”所有图片来填充实际使用之前的数组。我不确定如何实现这一点,因为我确实在我的 getProfilePicture
函数中尝试了一个完成处理程序,但这似乎没有帮助,这是我学会处理异步函数的一种方法。还有其他想法吗?谢谢!
【问题讨论】:
您的viewForHeaderInSection
没有返回视图。
哦,对不起,我把那部分遗漏了,最后应该有一个返回声明。
好的。当人们异步更新他们的图像视图时,“闪烁”的图像视图很常见,但你在这里没有这样做(你只是异步更新数组)。我看不出标题视图图像会闪烁的原因。我可能会建议dequeueReusableHeaderFooterViewWithIdentifier
而不是dequeueReusableCellWithIdentifier
(请参阅***.com/a/27843634/1271826),但我不会认为这会导致您描述的问题。我想知道您是否正在处理cellForRowAtIndexPath
中的图像。我在这里看不到任何会导致闪烁的东西。
@Rob 对不起,我忘了说上面的代码是我的代码的更新版本。我试图做的是首先将getProfilePicture
函数放入viewForHeaderInSection
函数中,结果,它不断调用getProfilePicture
函数,导致它闪烁。然后,我尝试了另一种方法,即预先在viewDidLoad
中获取照片,这就是我上面的代码中显示的内容。我现在在抓取viewDidLoad
中的图像时遇到问题,想知道人们是否可以提供帮助。对于误导性标题,我深表歉意。
好的,那么我显然无法评论闪烁。关于“预取”的想法,我不建议这样做(您真的想在应用程序检索图像时冻结应用程序,还是显示它可以做什么并在下载图像时弹出图像)。我宁愿看到你有viewForHeaderInSection
请求它需要的图像。最简单的方法是使用 SDWebImage 或 AFNetworking 提供的 UIImageView
异步图像检索类别。
【参考方案1】:
我有同样的问题,但我的是在 Objective-C 好吧,结构并没有那么不同,我所做的是添加条件: headerView.headerImage.image
这是我认为适合您的实施的改进解决方案..
因为您将self.getProfilePicture
放在viewDidLoad
中,所以它只会被调用一次,section
==0 只会包含一张图片,
如果self.creatorImages
的索引超出范围/界限,下面的代码将请求添加图像
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
//Show section header cell with image
var cellIdentifier = "SectionHeaderCell"
var headerView = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! SectionHeaderCell
if (section < self.creatorImages.count) // validate self.creatorImages index to prevent 'Array index out of range' error
if (headerView.headerImage.image == nil) // prevents the blinks
headerView.headerImage.image = self.creatorImages[section];
else // requests for additional image at section
// this will be called more than expected because of tableView.reloadData()
println("Loading Photo")
self.getProfilePicture (result, image) -> Void in
if(result == true)
//simply appending will do the work but i suggest something like:
if (self.creatorImages.count <= section)
self.creatorImages.append(image!)
tableView.reloadData()
println("self.creatorImages.count \(self.creatorImages.count)")
//that will prevent appending excessively to data source
else
println("Error loading image")
headerView.headerImage.clipsToBounds = true
headerView.headerImage.layer.cornerRadius = headerView.headerImage.frame.size.width / 2
return headerView
您的实现肯定与我的想法不同,但编辑历史记录中的代码并没有白费,对吧?.. 哈哈哈.. ;) 希望我对你有所帮助.. 干杯!
【讨论】:
我仍然收到错误消息。我在viewForHeaderInSection
函数中添加了该条件,但我仍然收到错误消息fatal error: Array index out of range
。我似乎能够加载第一张图片,但在第一张图片之后我无法加载任何内容。不过谢谢。还有其他想法吗?
在尝试访问索引之前检查数组计数
我的答案是删除闪烁/闪烁..关于那个致命错误..您需要检查数组的索引..因为您正在使用异步...我已经编辑我的答案看看..
所以你是说我只需要检查一下索引是否已填充?这样就可以解决所有问题?
是的!没错..实际上他的代码(sendAsynchronousRequest)需要做很多工作才能完美运行,他必须有一个缓存 url 和 id 以便它不会知道错误的图像......因为他是很多验证不为此使用外部/现成的框架..我也在在这里学习东西,所以谢谢你指出来.. :)以上是关于异步加载图像不断导致图像闪烁?的主要内容,如果未能解决你的问题,请参考以下文章