Search code examples
iosobjective-cicloudcloudkit

Service unavailable error (CKError Code 6) in CKContainer requestApplicationPermission


I am trying to read user's name from their iCloud account using CloudKit as below

CKContainer *container = [CKContainer defaultContainer];
[container accountStatusWithCompletionHandler:^(CKAccountStatus accountStatus, NSError * _Nullable error) {
    if (accountStatus == CKAccountStatusAvailable) {
        [container requestApplicationPermission:CKApplicationPermissionUserDiscoverability completionHandler:^(CKApplicationPermissionStatus applicationPermissionStatus, NSError * _Nullable error) {
            if (applicationPermissionStatus == CKApplicationPermissionStatusGranted) {
                [container fetchUserRecordIDWithCompletionHandler:^(CKRecordID * _Nullable recordID, NSError * _Nullable error) {
                    if (!error && recordID) {
                        [container discoverUserIdentityWithUserRecordID:recordID completionHandler:^(CKUserIdentity * _Nullable userInfo, NSError * _Nullable error) {
                            NSLog(@"UserInfo: %@  Error: %@", userInfo, error);
                        }];
                    }
                }];
            }
        }];
    }
}];

but every time requestApplicationPermission fails with Service Unavailable error and status is CKApplicationPermissionStatusCouldNotComplete. I am not sure what am I doing wrong here. I tried it with multiple devices and accounts but still result is same. I have tried disabling and enabling CloudKit in capabilities as was suggested in some places but no luck. Is there any information that I need to configure which I am missing. Below is how my iCloud capability looks

iCloud Capability Configuration


Solution

  • Well it turns out I needed to call statusForApplicationPermission: before calling requestApplicationPermission. It was really baffling that just because I did not check the permission status, the permission request was failing. That too with Service UnAvailable error. Here is the code that works(not very elegant):

    CKContainer *container = [CKContainer defaultContainer];
    [container accountStatusWithCompletionHandler:^(CKAccountStatus accountStatus, NSError * _Nullable error) {
        if (accountStatus == CKAccountStatusAvailable) {
            [container statusForApplicationPermission:CKApplicationPermissionUserDiscoverability completionHandler:^(CKApplicationPermissionStatus applicationPermissionStatus, NSError * _Nullable error) {
                if (applicationPermissionStatus==CKApplicationPermissionStatusInitialState || applicationPermissionStatus==CKApplicationPermissionStatusGranted) {
                    [container requestApplicationPermission:CKApplicationPermissionUserDiscoverability completionHandler:^(CKApplicationPermissionStatus applicationPermissionStatus, NSError * _Nullable error) {
                        if (applicationPermissionStatus == CKApplicationPermissionStatusGranted) {
                            [container fetchUserRecordIDWithCompletionHandler:^(CKRecordID * _Nullable recordID, NSError * _Nullable error) {
                                if (!error && recordID) {
                                    [container discoverUserIdentityWithUserRecordID:recordID completionHandler:^(CKUserIdentity * _Nullable userInfo, NSError * _Nullable error) {
                                        NSLog(@"UserInfo: %@  Error: %@", userInfo, error);
                                    }];
                                }
                            }];
                        }
                    }];
                }
            }];
        }
    }];