如何加速 Cloudkit 'fetchRecordWithID'

How to speed up Cloudkit 'fetchRecordWithID'

我的应用程序在第一次打开时做的第一个操作是在 cloudkit 检查是否有任何信息连接到用户 iCloud 帐户,因为如果有,信息将下载到应用程序。我的问题是,下载信息的方法在通过 wifi 连接时需要大约 13 秒来收集信息,而在使用移动数据时需要超过 45 秒。我一直在寻找优化,发现使用 development 数据库进行模拟时,结果比使用 produciton 数据库进行模拟时更快,所以我可能以错误的方式收集数据,因为有很多生产中的数据多于开发中的数据。

搜索信息的方法如下

CKRecordID *recordID = [[CKRecordID alloc] initWithRecordName: userKey];

[_publicDatabase fetchRecordWithID:recordID completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
        if (error) {
            NSLog(@"Error in fethcing from user db %@", error);
            completion(error);
        } else {

            NSLog(@"User found in db");
            NSString *name = record[@"Name"];
            CKAsset *file = record[@"Image"];
            NSString *url = file.fileURL.absoluteString;
            NSMutableArray<NSString*> *codes = record[@"Groups"];

            NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString * basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
            NSData * binaryImageData = [NSData dataWithContentsOfURL:[file fileURL]];
            [binaryImageData writeToFile:[basePath stringByAppendingPathComponent:@"profilePicture.png"] atomically:YES];

            completion(nil);
        }

    }];

云端的信息基本就是姓名,头像,群号

有什么方法可以加快从 cloudkit 中获取数据的速度?因为我不认为通过移动数据获取此数据需要超过 45 秒是正常的,所以这没有意义。

你应该使用 CKFetchRecordsOperation class 而不是 CKDatabase 提供的 fetch 函数。

原因是CKFetchRecordsOperation继承自Operationclass,允许更复杂和扩展的性能配置。

这是您的代码修改以使用上面提到的 class。

let fetchOperation: CKFetchRecordsOperation = CKFetchRecordsOperation(recordIDs: [ userKey ])
// Fetch only desired keys
fetchOperation.desiredKeys = [ "Name", "Image", "Groups" ]
// Performance tips
operation.qualityOfService = .userInitiated

fetchOperation.perRecordCompletionBlock = { (record: CKRecord?, recordID: CKRecordID?, error: Error) -> (Void) in
    guard let record = record else
    {
        print("There's no record in this fetch operations")

        if let error = error
        {
            print("err @ \(#function) -> \(error.localizedDescription)")
        }

        return
    }

    Dispatch.async.main 
    {
        // Save your image here...
    }
}

_publicDatabase.add(fetchOperation)

这里有一些提示...

  1. 只获取您需要的那些字段。使用 dediredKeys 属性
  2. 设置操作的优先级。想想这是后台操作,还是用户现在需要响应。更多信息请见 qualityOfService 属性
  3. 当您保存图片时,请在主队列以及用户响应中进行保存。

PS:我现在注意到您的代码是 Objective-C,我的示例是 Swift,抱歉。