Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS CloudKit crash on completion block for -fetchUserRecordIDWithCompletionHandler:

I'm writing an initialization method for CloudKit. The problem I'm having occurs while fetching the user id/account status.

I'm calling [[CKContainer defaultContainer] fetchUserRecordIDWithCompletionHandler:].

It crashes a little while later and the debugger points me to the "Queue: com.apple.cloudkit.operation.callback (serial) queue" thread.

This method is the only CloudKit related method with a callback that should be getting executed.

Here's the method itself:

[[CKContainer defaultContainer] fetchUserRecordIDWithCompletionHandler:^(CKRecordID *recordID, NSError *error) {
    NSLog(@"CLOUDKIT Fetching User Record ID");

    if (error) {
        NSLog(@"[%@] Error loading CloudKit user: %@", self.class, error);
    }

    if (recordID) {
        NSLog(@"CLOUDKIT Found User Record ID: %@", recordID.recordName);

        // If there is a record ID we check for account status
        [[CKContainer defaultContainer] accountStatusWithCompletionHandler:^(CKAccountStatus accountStatus, NSError *error) {
            NSLog(@"CLOUDKIT Finding Account Status");

            if (error) {
                NSLog(@"[%@] Error checking CloudKit availability: %@", self.class, error);
            }

            if (accountStatus == CKAccountStatusAvailable) {
                NSLog(@"CLOUDKIT Account Available, beginning initial sync");
                // We have an available account. If we have a new user do a complete sync
                NSString *userRecordID = [[NSUserDefaults standardUserDefaults] stringForKey:CLOUD_KIT_CURRENT_USER_ID_USER_DEFAULT];
                if (userRecordID == nil || ![recordID.recordName isEqualToString:userRecordID]){
                    [self syncAllData];
                } else {
                    // If there haven't been any updates, just sync as usual
                    [self syncChanges];
                }

                // Subscribe to zone updates
                [self subscribeToDefaultZoneUpdates];
            } else {
                NSLog(@"[%@] Cloudkit account is either unavailable or restricted", self.class);
            }
        }];
    } else {
        NSLog(@"[%@] CloudKit user Record ID not found", self.class);
    }
}];

There are NSLogs before and after this that are being executed but the NSLog at the very top ("CLOUDKIT Fetching User Record ID") never gets executed.

When it crashes the log doesn't give me any information. Here is the thread queue from Xcode:

enter image description here

Here's what it actually spits out in the debug navigator.

libsystem_kernel.dylib`__pthread_kill:
0x332f7df4:  mov    r12, #0x148
0x332f7df8:  svc    #0x80
0x332f7dfc:  blo    0x332f7e14                ; __pthread_kill + 32
0x332f7e00:  ldr    r12, [pc, #4]             ; __pthread_kill + 24
0x332f7e04:  ldr    r12, [pc, r12]
0x332f7e08:  b      0x332f7e10                ; __pthread_kill + 28
0x332f7e0c:  rsbeq  lr, r6, #0x80000001
0x332f7e10:  bx     r12
0x332f7e14:  bx     lr

Specifically, it is breaking at 0x332f7dfc: blo 0x332f7e14 ; __pthread_kill + 32

like image 849
Jonathan Avatar asked Oct 20 '22 02:10

Jonathan


1 Answers

The order of your methods are not right/incomplete. This is what you should do: You first have to call the accountStatusWithCompletionHandler to see if you are loged in to iCloud. Then if that is the case you have to call the requestApplicationPermission to see if you are allowed to query iCloud. And if that is true then you can execute the fetchUserRecordIDWithCompletionHandler to get your ID and after that you execute the discoverUserInfoWithUserRecordID to get the details. If you want to see a sample, then have a look at the CloudKitAtlas demo from Apple: https://developer.apple.com/library/prerelease/ios/samplecode/CloudAtlas/Introduction/Intro.html#//apple_ref/doc/uid/TP40014599-Intro-DontLinkElementID_2

like image 135
Edwin Vermeer Avatar answered Nov 14 '22 22:11

Edwin Vermeer