EXC_BAD_ACCESS using iCloud on multiple devices

2019-02-14 14:36发布

问题:

I'm creating an app with iCloud. But I have some problem. It creates directory on iCloud using NSFileWrapper, then it creates NSData (container) file in NSFileWrapper directory. I'm using this code to convert NSFileWrapper to NSMutableArray:

NSFileWrapper *MyWrapper=[[[MyDocument data] fileWrappers] objectForKey:@"myFile.doh"];
    NSData *MyData=[NSData dataWithData:[MyWrapper regularFileContents]];
    NSMutableArray *MyList=[NSPropertyListSerialization propertyListFromData:MyData mutabilityOption:NSPropertyListMutableContainers format:nil errorDescription:nil];

And it works correctly only on the device, which has created this container. On other devices the result of this code is BAD_ACCESS (in the second line of the code, where I start doing something with data). While debugging, function "regularFileContents" returns correct object with correct data size, but when I try to read this data, BAD_ACEESS(code=10) happens.

I'm using ARC, so it's not an error of memory management.

May be the problem is in some project/code sign settings? Any ideas?

Thanks!

回答1:

I ran into this as well and after much experimentation I've found that even though the outer wrapper has downloaded the inner contents have not actually downloaded yet and that causes the call to regularFileContents to fail.

I've been calling startDownloadingUbiquitousItemAtURL on MyWrapper and once that completes the error is gone. Here's a method that checks the downloaded status of a file (assuming you know the url to your MyWrapper) and starts the download if it isn't downloaded yet.

-(BOOL)downloadFileIfNotAvailable:(NSURL*)fileURL
{
    NSNumber *isInCloud = nil;

    if ([fileURL getResourceValue:&isInCloud forKey:NSURLIsUbiquitousItemKey error:nil])
    {
        if ([isInCloud boolValue]) {
            NSNumber *isDownloaded = nil;
            if ([fileURL getResourceValue:&isDownloaded forKey:NSURLUbiquitousItemIsDownloadedKey error:nil])
            {
                if ([isDownloaded boolValue])
                {
                    return YES;
                }

                NSError *error = nil;
                [[NSFileManager defaultManager] startDownloadingUbiquitousItemAtURL:fileURL error:&error];

                if (error)
                {
                    NSLog(@"Download Failed :: %@", error);
                }

                return NO;
            }
        }
    }

    return YES;
}