Question


i'm new in programming iOS and now I have got the problem that I couldn't get a iCloud connection if I run my app on a real device.
The app runs perfect on the simulator and also if I disconnect the device from my mac.
Have anybody an idea how I can fix it?
This is the code I have written to connect to the iCloud

    self.fileManager = [NSFileManager defaultManager];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        self.ubiquityIdentifier = [self.fileManager URLForUbiquityContainerIdentifier:nil];
    });

    dispatch_async(dispatch_get_main_queue(), ^{
        if(self.ubiquityIdentifier)
        {
            [[NSNotificationCenter defaultCenter] postNotificationName:kiCloudAvailableNotification object:self.ubiquityIdentifier];
            [self startMediaQuery];
        }
        else
        {
            [[NSNotificationCenter defaultCenter] postNotificationName:kiCloudNotAvailableNotification object:self.ubiquityIdentifier];
            NSLog(@"iCloud not available");
        }
    });

If the device is connected I only go in the else block and if I test it in the simulator or on a not connected device everything works fine.
Thanks a lot.
weissja19

Was it helpful?

Solution

Assuming that you're detecting failure because that NSLog prints its "iCloud not available" message, you're setting up a classic race condition here:

  1. You set the value of self.ubiquityIdentifier on a global (non-main) queue.
  2. You test the value self.ubiquityIdentifier on the main queue.

The two dispatch_async calls run on different queues. As a result, there's no guarantee that you're setting the value of self.ubiquityIdentifier before you test it. It will work sometimes, and fail at others, and not necessarily for any obvious reason. When you get the "iCloud not available" message, it's because the second queue checked the value before you assigned any value.

The fix is to change the dispatch calls so that you can guarantee the order of execution. Two possibilities are:

  1. Combine these two dispatch_async calls so that all of the code happens on the same queue, or
  2. Move the second dispatch_async inside the first, so that you don't dispatch back to the main queue until you've set a value for self.ubiquityIdentifier.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top