我有一个对象数组(其中包括从 Google Places API 下载照片所需的数据),当我尝试在 tableView 单元格中加载这些对象的元素时,图像和 titleLabels 不断切换,而滚动。
这是我的 cellForRowAtIndexPath 的 tableView 函数
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("TestTableViewCell", forIndexPath: indexPath) as! TestTableViewCell
let business = businessObjects[indexPath.row]
if businessShown[indexPath.row] == false{
self.getImageFromPhotoReference(business.businessPhotoReference) { (photo, error) -> Void in
cell.backgroundImage.image = photo
}
}
cell.businessNameLabel.text = business.businessName
businessShown[indexPath.row] = true
return cell
}
func getImageFromPhotoReference(photoReference: String, completion: (photo: UIImage, error: NSError?) -> Void){
let photoRequestParams = ["key":"##", "photoreference": photoReference, "maxheight": "800"]
let placePhotoURLString = self.googleClient.buildPlacePhotoURLString(photoRequestParams)
let photoRequestURL = NSURL(string: placePhotoURLString)!
self.getDataFromUrl(photoRequestURL) { (data, response, error) -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
guard let data = NSData(contentsOfURL: photoRequestURL) where error == nil else { return }
let imageFile = UIImage(data: data)!
completion(photo: imageFile, error: error)
})
}
}
private func getDataFromUrl(url: NSURL, completion: ((data: NSData?, response: NSURLResponse?, error: NSError? ) -> Void)) {
NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
completion(data: data, response: response, error: error)
}.resume()
}
谢谢你
问题是,当重用的单元已经在其上加载了新数据时,异步网络调用就会完成。我的建议是使用像 Kingfisher 或 HanekeSwift 这样的图像缓存实用程序,因为它们会自动取消单元重用时的异步调用,并缓存图像,从而减少网络调用。
您的代码不是线程安全的,至少您应该在完成处理程序中检查您尝试用图像填充的单元格是否仍然位于开始异步图像加载时的同一位置。例如,您可以将单元格视图的标签设置为等于项目编号,如果您加载了图像但单元格标签已更改,请不要触摸该单元格的背景图像