UITableView 在显示图像时滞后 Swift
UITableView is Lagging when Displaying Images Swift
我有一个 tableView
在单元格中显示图像,我正在 viewDidLoad
函数中获取数据
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCellWithIdentifier("cardSelectionCell", forIndexPath: indexPath) as! MyCell
let card = fetchedResultsController.objectAtIndexPath(indexPath) as! Card
cell.Name?.text = card.name
var image: NSData = card.photo as NSData
cell.logo.image = UIImage(data: image)
let date = NSDate()
let formatter = NSDateFormatter()
formatter.timeStyle = .MediumStyle
cell.policyExpiryDate.text = formatter.stringFromDate(date)
return cell
}
但问题是当我开始滚动时,tableView
非常滞后
所以我尝试创建一个字典来转换 viewDidLoad
()
中的图像
var imageDictionary = [Card:UIImage]()
AllCards = context.executeFetchRequest(request, error: nil) as! [Card]
for card in AllCards {
imageDictionary[card] = UIImage(data: card.photo as NSData)
}
并在 tableView
函数中:
cell.logo.image = imageDictionary[card]
但它仍然滞后
还有一个问题:如果在核心数据中添加一张卡片,我必须再次获取图像数组,所以我尝试在viewDidAppear()
中创建数组,但图像没有出现在第一次加载,tableView 仍然滞后。
首先,这实际上取决于您的图片大小:
var image: NSData = card.photo as NSData
cell.logo.image = UIImage(data: image)
这行可能很重。您可以像这样轻松测量它,例如:
let time1 = CACurrentMediaTime()
var image: NSData = card.photo as NSData
cell.logo.image = UIImage(data: image)
print(CACurrentMediaTime() - time1)
如果花费的时间比您应该优化的时间长(例如超过 8 毫秒)。您可以通过多种方式实现它,例如,您可以将 UIImage
引用存储在某个字典或数组中,然后在 cellForIndexPath:
中继续显示。
另一种方法是 AsyncKit 方式 - 让你的 UI 异步,在一个线程中加载数据并将其传递给仅在主线程上绘制。现在你所有的处理都在主线程中。
UPD:我认为在这种情况下最好的方法是存储图像的路径,然后 运行 在后台进程中进行 UI 图像调整大小和 return 预览。您还可以为调整大小和未调整大小的 UIImage 创建缓存,路径或 URL 可以是一个键 - 所以下次只需从缓存中获取 UIImage 不启动重新调整大小。
还要注意这个操作:
cell.logo.image = UIImage(data: image)
创建一个系统缓存并可以在内存中进行大量分配,因为垃圾收集器不会像 UIWebView
那样立即将其杀死。所以你可以像这样在你的函数周围添加你自己的自动释放池:
autoreleasepool { () -> () in
cell.logo.image = UIImage(data: image)
}
我也有这个问题,我用dispatch_async
解决了。这样 table 单元格将在图像完成加载之前加载。
let priority = DISPATCH_QUEUE_PRIORITY_HIGH
dispatch_async(dispatch_get_global_queue(priority, 0)) {
if let imgData = card.photo as? NSData {
let image = UIImage(data: imageData)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
cell.logo.image = image
})
}
}
我有一个 tableView
在单元格中显示图像,我正在 viewDidLoad
函数中获取数据
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCellWithIdentifier("cardSelectionCell", forIndexPath: indexPath) as! MyCell
let card = fetchedResultsController.objectAtIndexPath(indexPath) as! Card
cell.Name?.text = card.name
var image: NSData = card.photo as NSData
cell.logo.image = UIImage(data: image)
let date = NSDate()
let formatter = NSDateFormatter()
formatter.timeStyle = .MediumStyle
cell.policyExpiryDate.text = formatter.stringFromDate(date)
return cell
}
但问题是当我开始滚动时,tableView
非常滞后
所以我尝试创建一个字典来转换 viewDidLoad
()
var imageDictionary = [Card:UIImage]()
AllCards = context.executeFetchRequest(request, error: nil) as! [Card]
for card in AllCards {
imageDictionary[card] = UIImage(data: card.photo as NSData)
}
并在 tableView
函数中:
cell.logo.image = imageDictionary[card]
但它仍然滞后
还有一个问题:如果在核心数据中添加一张卡片,我必须再次获取图像数组,所以我尝试在viewDidAppear()
中创建数组,但图像没有出现在第一次加载,tableView 仍然滞后。
首先,这实际上取决于您的图片大小:
var image: NSData = card.photo as NSData
cell.logo.image = UIImage(data: image)
这行可能很重。您可以像这样轻松测量它,例如:
let time1 = CACurrentMediaTime()
var image: NSData = card.photo as NSData
cell.logo.image = UIImage(data: image)
print(CACurrentMediaTime() - time1)
如果花费的时间比您应该优化的时间长(例如超过 8 毫秒)。您可以通过多种方式实现它,例如,您可以将 UIImage
引用存储在某个字典或数组中,然后在 cellForIndexPath:
中继续显示。
另一种方法是 AsyncKit 方式 - 让你的 UI 异步,在一个线程中加载数据并将其传递给仅在主线程上绘制。现在你所有的处理都在主线程中。
UPD:我认为在这种情况下最好的方法是存储图像的路径,然后 运行 在后台进程中进行 UI 图像调整大小和 return 预览。您还可以为调整大小和未调整大小的 UIImage 创建缓存,路径或 URL 可以是一个键 - 所以下次只需从缓存中获取 UIImage 不启动重新调整大小。
还要注意这个操作:
cell.logo.image = UIImage(data: image)
创建一个系统缓存并可以在内存中进行大量分配,因为垃圾收集器不会像 UIWebView
那样立即将其杀死。所以你可以像这样在你的函数周围添加你自己的自动释放池:
autoreleasepool { () -> () in
cell.logo.image = UIImage(data: image)
}
我也有这个问题,我用dispatch_async
解决了。这样 table 单元格将在图像完成加载之前加载。
let priority = DISPATCH_QUEUE_PRIORITY_HIGH
dispatch_async(dispatch_get_global_queue(priority, 0)) {
if let imgData = card.photo as? NSData {
let image = UIImage(data: imageData)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
cell.logo.image = image
})
}
}