5
votes

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

2
Are you actually crashing or just breaking? Meaning, if you hit "continue" in the debugger, do you continue? Have you tried hitting it until something happens? Do you have an "all exceptions" breakpoint enabled? Which specific line are you breaking on? Sometimes Apple's API's will throw non-fatal exceptions for whatever reason, I've seen it with AVAudioPlayer. - Reid
Hitting continue doesn't give me any new information. It just spits out more assembly until I get to a trap. It doesn't give me a line number. The break is in the debug navigator. - Jonathan
The point where it is actually breaking looks like this: 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 - Jonathan
That wasn't very pretty. I added it to the original question. - Jonathan

2 Answers

3
votes

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

0
votes

Okay, so I did figure this one out.

I rolled back to the last working and changed everything except for some binaries generated by FastPDFKit. After I did that it started working fine. No clue what in there was messing it up but it works now.