Swift CloudKit表滚动速度慢-更改现有代码?
下面我有我现有的查询下载和表格行代码的单元格Swift CloudKit表滚动速度慢-更改现有代码?,swift,image,uitableview,scroll,cloudkit,Swift,Image,Uitableview,Scroll,Cloudkit,下面我有我现有的查询下载和表格行代码的单元格 publicDB.perform(query, inZoneWith: nil) { (results, error) -> Void in if (error != nil) { self.present(alert, animated: true, completion: nil) } else {
publicDB.perform(query, inZoneWith: nil)
{
(results, error) -> Void in
if (error != nil)
{
self.present(alert, animated: true, completion: nil)
}
else
{
for result in results!
{
self.restaurantArray.append(result)
}
OperationQueue.main.addOperation( { () -> Void in
self.tableView.reloadData()
}) } }}
downloadRestaurants()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "restaurantcell") as? RestaurantTableCell
let restaurant: CKRecord = restaurantArray[indexPath.row]
cell?.name?.text = restaurant.value(forKey: "Name") as? String
let asset = restaurant.value(forKey: "Picture") as! CKAsset
let data = try! Data(contentsOf: asset.fileURL)
_ = UIImage(data: data)
cell?.picture?.image = UIImage(data: data)
return cell!
}
当我运行这段代码时,应用程序仍能正常运行,但在大约10个表格单元格中滚动时,会出现令人难以置信的波动。我不确定是什么原因造成的-所有记录,每个都包含一个图像,都是在top函数的查询下载部分下载的。然而,我缺少的一个问题或概念在运行时始终存在。我错过了什么?延迟加载?隐藏物还有别的吗?目前还不确定,所以任何帮助都会非常有用
更新1:
我更新了我的代码,非常感谢你来到皮尔斯。我不得不从他的回答中稍微更新我的代码,以维护一个ckrecord数组,通过-restaurantArray切换到另一个控制器,同时也为NSObject类-tablerestaurantarray创建一个新数组,以显示在当前表控制器中
var restaurantArray: Array<CKRecord> = []
var tablerestaurantarray: [Restaurant] = []
for result in results!
{
let tablerestaurant = Restaurant()
if let name = result.value(forKey: "Name") as! String? {
tablerestaurant.name = name
}
// Do same for image
if let imageAsset = result.object(forKey: "Picture") as! CKAsset? {
if let data = try? Data(contentsOf: imageAsset.fileURL) {
tablerestaurant.image = UIImage(data: data)
}
}
self.tablerestaurantarray.append(tablerestaurant)
self.restaurantArray.append(result)
}
OperationQueue.main.addOperation( { () -> Void in
self.tableView.reloadData()
})
}
}
}
downloadRestaurants()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return restaurantArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "restaurantcell") as? RestaurantTableCell
let restaurant: Restaurant = tablerestaurantarray[indexPath.row]
cell?.name?.text = restaurant.name
cell?.picture?.image = restaurant.image
return cell!
}
代码的设置方式,无论何时在UITableView中滚动,您的程序都在将CKAsset转换为数据,然后将其转换为UIImage,这在每个单元格中!这是一个相当低效的过程,因此请尝试创建一个名为Restaurant之类的对象,该对象具有image属性,当您查看从CKQuery返回的所有记录时,将每个记录解析为一个新的Restaurant对象。要创建新的NSObject,请转到文件->新建->文件->选择“Swift文件”,并添加如下内容:
import UIKit
class Restaurant: NSObject {
// Create a UIImage property
var image: UIImage?
// Add any other properties, i.e. name, address, etc.
var name: String = ""
}
现在请回答您的问题:
// Create an empty array of Restaurant objects
var restaurantArray: [Restaurant] = []
publicDB.perform(query, inZoneWith: nil) { (results, error) -> Void in
if (error != nil) {
self.present(alert, animated: true, completion: nil)
} else {
for result in results! {
// Create a new instance of Restaurant
let restaurant = Restaurant()
// Use optional binding to check if value exists
if let name = result.value(forKey: "Name") as! String? {
restaurant.name = name
}
// Do same for image
if let imageAsset = result.object(forKey: "Picture") as! CKAsset? {
if let data = try? Data(contentsOf: imageAsset.fileURL) {
restaurant.image = UIImage(data: data)
}
}
// Append the new Restaurant to the Restaurants array (which is now an array of Restaurant objects, NOT CKRecords)
self.restaurantArray.append(restaurant)
}
OperationQueue.main.addOperation( { () -> Void in
self.tableView.reloadData()
})
}
}
现在,您的单元设置更简单:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "restaurantcell") as? RestaurantTableCell
let restaurant: Restaurant = restaurantArray[indexPath.row]
cell?.name?.text = restaurant.name
cell?.picture?.image = restaurant.image
return cell!
}
您应该使用以实现UITableView的分页
您必须将属性设置为一个数字,该数字等于表上一次可访问的单元格数量加上3或4
在必须实现将应用于一条CKRecord的代码的位置设置属性
设置属性。这是分页代码中最重要的部分,因为此闭包接收可选的CKQueryCursor参数
如果此CKQueryCursor为nil,则您已到达可供查询的最后一条记录,但如果它是非nil值,则您将有更多记录要使用此CKQueryCursor作为下一次提取的指示符进行提取
当用户在TableView上滚动并到达最后一个元素时,您应该使用CKQueryCursor执行另一次获取
其他性能建议是,应在单独的执行队列中处理CKAssets。每次在tableView中滚动时,应用程序都必须将CKAsset转换为数据,然后将其转换为UIImage。我建议创建一种称为Restaurant之类的NSObject,然后在执行查询时,从CKRecords数组中获取每条记录,并将其解析为具有UIImage属性的Restaurant对象,然后使用这些对象中的图像填充单元格。这样,它只需要抓取一个UIImage,而不是每次都转换它。皮尔斯,你能提供一个代码示例吗?在我的项目中,我以前从未使用过NSObjects,所以我在这方面有点落后。请看下面我的答案。皮尔斯,我非常感谢你的答案。请看一下我的更新代码。问题是。。。虽然代码按预期工作,但在最初的几个滚动过程中有轻微的减速。然而,一旦我坐到桌子的底部,一切都像我希望的那样快。你知道吗?如果你第一次滚动浏览图像时图像还没有被缓存,那么当你把它放到底部时,每个图像都会被缓存,这可能是一个非常典型的问题。查看此答案以查看解决方案-注意:答案在Objective-C中,但在最顶端有一个链接指向GitHub gist,该GitHub gist在Swift中具有相同的解决方案。祝你好运