CKDiscoverAllContactsOperation 在 iOS 10 下停止工作

CKDiscoverAllContactsOperation stopped working under iOS 10

我有一个支持 iOS 8 及更高版本的应用程序。我一直在使用 CKDiscoverAllContactsOperation 来获取用户列表以供共享。此代码在 iOS 8 和 iOS 9 下工作正常。但是在 iOS 10 下,完成块 returns 没有错误,但它也 returns 没有结果,即使有一些。

我还在控制台中注意到以下消息:

<Error>: Got a user discovery progress callback with no record id: { }

这出现在操作开始和调用完成块之间。

相关代码如下:

CKDiscoverAllContactsOperation *op = [[CKDiscoverAllContactsOperation alloc] init];
op.discoverAllContactsCompletionBlock = ^(NSArray <CKDiscoveredUserInfo *> *userInfos, NSError *error) {
    if (error) {
        NSLog(@"Unable to get all app users: %@", error);
    } else {
        // process the found users
    }
};
[container addOperation:op];

我知道 CKDiscoverAllContactsOperation 自 iOS 10 起已被弃用,并已被 CKDiscoverAllUserIdentitiesOperation 取代。但是由于我的应用程序支持回到 iOS 8,所以即使在 iOS 10 下我也没有任何理由不能使用相同的代码。事实上,我仍然使用其他几个已弃用的(如iOS 10) CloudKit 类 这是唯一给我一个问题的。

经过一些研究,似乎 CKDiscoverAllContactsOperation 根本无法正常工作,因为它应该在 iOS 10 下工作。这可能是 iOS 10 中的一个错误,将提交一个错误与苹果公司。但我现在有用户抱怨,现在需要解决方法。

最简单的解决方案是在可用时使用新操作,在不可用时使用旧操作。

这导致了以下基本代码:

if ([CKDiscoverAllUserIdentitiesOperation class]) {
    // Use the newer operation
    CKDiscoverAllUserIdentitiesOperation *op = [[CKDiscoverAllUserIdentitiesOperation alloc] init];
    NSMutableArray *users = [NSMutableArray array];
    op.userIdentityDiscoveredBlock = ^(CKUserIdentity *identity) {
        if (identity.hasiCloudAccount) {
            DatabaseShareUser *user = [[DatabaseShareUser alloc] init];
            user.recordId = identity.userRecordID;
            user.username = [NSPersonNameComponentsFormatter localizedStringFromPersonNameComponents:identity.nameComponents style:NSPersonNameComponentsFormatterStyleDefault options:0];
            [users addObject:user];
        }
    };
    op.discoverAllUserIdentitiesCompletionBlock = ^(NSError *error) {
        if (error) {
            NSLog(@"Unable to get app users: %@", error);

            completion(nil);
        } else {
            completion([users copy]);
        }
    };

    [container addOperation:op];
} else {
    // Use the old operation
    CKDiscoverAllContactsOperation *op = [[CKDiscoverAllContactsOperation alloc] init];
    op.discoverAllContactsCompletionBlock = ^(NSArray <CKDiscoveredUserInfo *> *userInfos, NSError *error) {
        if (error) {
            NSLog(@"Unable to get app users: %@", error);

            completion(nil);
        } else {
            NSMutableArray *res = [NSMutableArray array];
            for (CKDiscoveredUserInfo *userInfo in userInfos) {
                DatabaseShareUser *user = [[DatabaseShareUser alloc] init];
                user.recordId = userInfo.userRecordID;
                user.username = userInfo.displayName;
                [res addObject:user];
            }

            completion([res copy]);
        }
    };
    [container addOperation:op];
}

DatabaseShareUser 是一个简单的应用程序 class,它存储每个用户的 CKRecordID 和显示名称。

completion 是此代码所在方法使用的完成块。