I'm trying to switch from Parse to CloudKit and got my sample working so far. I got a CLoudKitModel which looks like this:
class CloudKitModel {
let container: CKContainer
let privateDB: CKDatabase
let publicDB: CKDatabase
init() {
container = CKContainer.defaultContainer()
privateDB = container.privateCloudDatabase
publicDB = container.publicCloudDatabase
}
func getPlayers(completionHandler: (data: [CloudKitPlayers]?, success: Bool) -> ()) {
var playerArray = [CloudKitPlayers]()
let predicate = NSPredicate(value: true)
let sort = NSSortDescriptor(key: "sortID", ascending: true)
let query = CKQuery(recordType: "Player", predicate: predicate)
query.sortDescriptors = [sort]
let operation = CKQueryOperation(query: query)
operation.recordFetchedBlock = { (record) in
let players = CloudKitPlayers()
players.age = record["age"] as! Int
players.name = record["name"] as! String
players.nickname = record["nickname"] as! String
players.position = record["position"] as! String
let imageData = record["image"] as! CKAsset
players.image = UIImage(contentsOfFile: imageData.fileURL.path!)
playerArray.append(players)
}
operation.queryCompletionBlock = { (cursor, error) in
if error == nil {
print("Fetched all players")
if playerArray.count > 0 {
completionHandler(data: playerArray, success: true)
} else {
completionHandler(data: nil, success: false)
}
}
}
self.publicDB.addOperation(operation)
}
}
and I call this getPlayers(completionHandler: )
function in an UITableViewController
:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let cloudKit = CloudKitModel()
cloudKit.getPlayers { (data, success) in
if success {
if let playerArray = data {
self.players = playerArray
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
print("reloaded tableView")
}
} else {
print("no success")
}
}
}
The problem is: It takes on average about 10 seconds to display the names in the TableView. It's not that I'm getting like a thousand records at once, these are just 8 data-sets that I'm loading from iCloud. I read that I should perform the tableView.reloadData()
on the main thread, but that didn't help either.
Is there something else that I'm missing or a particular way how to debug this? Compared the Parse this solution is like 10x slower...
Thanks for any ideas!
您可以尝试设置QOS吗?
operation.qualityOfService = .UserInitiated
To get the most speed, you most likely you'll want to load the CKAsset images asynchronously , so wrap the player image loads in a background thread operation block.
Here is and example from my code that fetches photo's that you can extrapolate from:
var backgroundQueue = NSOperationQueue()
func fetchPhoto(completion:(photo: UIImage!) -> ()) {
backgroundQueue.addOperationWithBlock() {
let image = self.record["Photo"] as? CKAsset
if let ckAsset = image {
let url = ckAsset.fileURL
if let imageData = NSData(contentsOfURL:url) {
self.photo = UIImage(data: imageData)
}
}
completion(photo: self.photo)
}
}
Then for the table load in cellForRowAtIndexPath
you can load the image via the completion block, but you MUST put all UI on the main thread or you will experience random crashes, as in:
object.fetchPhoto {
image in
dispatch_async(dispatch_get_main_queue()) {
cell.photo.image = image
}
}
I also encountered the same problem.
4 records took 12 seconds to load.
Problem
Performance issues come from CKAsset
Solution
My solution is remove CKAsset
(avatar/image). Store avatar/image in icloud storage (Usage is a little complicated).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.