下面我有现有的查询下载和表行代码的单元格......
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!
}
答案 0 :(得分:1)
设置代码的方式,无论何时滚动UITableView
,您的程序都会将CKAsset
转换为Data
,然后将其转换为UIImage
,这就是每个细胞!这是一个相当低效的过程,因此尝试创建一个名为Restaurant
的NSObject,它具有image属性,当您浏览从CKQuery
返回的所有记录时,将每条记录解析为一个新的{{ 1}}对象。要创建新的Restaurant
,请转到文件 - &gt;新 - &gt;档案 - &gt;选择'Swift File'并添加如下内容:
NSObject
现在查询:
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()
})
}
}
答案 1 :(得分:0)
您应该使用CKQueryOperation来实现UITableView的分页。
您必须将resultLimit属性设置为一个数字,该数字等于您在桌面上一次可见的单元格数量加3或4
设置recordFetchedBlock属性,您必须在其中实现将应用于一个CKRecord的代码
设置queryCompletionBlock属性。这是您的分页代码中最重要的部分,因为此闭包接收可选的CKQueryCursor参数。
如果这个CKQueryCursor为nil,那么你已经到达了可用于查询的最后一条记录,但是如果它是一个非零值,那么你有更多的记录可以使用这个CKQueryCursor作为下一次获取的指示器来获取。
当用户在TableView上滚动并到达最后一个元素时,您应该使用CKQueryCursor执行另一次提取。
其他性能建议是应在单独的执行队列中处理CKAssets。