2
votes

I have the same issue as this question where the iCloud ubiquity container is not being cleaned up when I delete the app.

But when I try to delete the ubiquity container I get an error message (The operation couldn’t be completed. (Cocoa error 513.)). How can I delete it? This is what I'm using:

NSString *path = @"/private/var/mobile/Library/Mobile Documents/XXXXXX";
[[NSFileManager defaultManager] removeItemAtPath:path error:&error];

EDIT: Even if I delete the App on the device and all iCloud data (Settings App->iCloud->Storage & Backup->Manage Storage->App Name) there's still some data left over on the iCloud ubiquity container. This is the data I want to delete the first time the app is launched (in case the user re-installs the app).

1
Post details of the error in error.userInfo NSLog(@" error is %@", error.userInfo);Duncan Groenewald
Best to get the ubiquity container like so NSURL *iCloudURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:_ubiquityID]; where _ubiquityID is the iCloud container identifier for your app.Duncan Groenewald
And your App may only have permission to remove anything inside this directory.Duncan Groenewald
The error is: The operation couldn’t be completed. (Cocoa error 513.)kroger

1 Answers

3
votes

You should be able to remove files INSIDE the ubiquity container by going to Settings App->iCloud->Storage & Backup->Manage Storage->App Name and then delete any files. I think you may only see files in the iCloud/Documents directory though so you may need code to clear anything else.

Alternately use a Mac and go to ~/Library/Mobile Documents and remove files there.

To get the iCloud container use this:

NSURL *iCloudURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:ubiquityID];

where ubiquityID is your apps iCloud container ID.

To list all files in the iCloud container use something like this passing in the iCloudURL

/*! Recursively lists all files

 @param dir The directory to list
 @param padding A string padding to indent the output depending on the level of recursion
 */
- (void)listAllFilesInDirectory:(NSURL*)dir padding:(NSString*)padding {

    NSArray *docs = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:dir includingPropertiesForKeys:nil options:0 error:nil];

    for (NSURL* document in docs) {

        FLOG(@" %@ %@", padding, [document lastPathComponent]);

        BOOL isDir;
        BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:document.path isDirectory:&isDir];

        if (fileExists && isDir) {
            [self listAllFilesInDirectory:document padding:[NSString stringWithFormat:@"  %@", padding]];
        }

    }
}

And to delete stuff from the ubiquity container you need to user a fileCoordinator something like this:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
    NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];

    [fileCoordinator coordinateWritingItemAtURL:fileURL options:NSFileCoordinatorWritingForDeleting
                                              error:nil byAccessor:^(NSURL* writingURL) {
                                                  NSFileManager* fileManager = [[NSFileManager alloc] init];
                                                  NSError *er;
                                                  //FLOG(@" deleting %@", writingURL);
                                                  bool res = [fileManager removeItemAtURL:writingURL error:&er];
                                                  if (res) {
                                                      LOG(@"   iCloud files removed");
                                                  }
                                                  else {
                                                      LOG(@"   document NOT removed");
                                                      FLOG(@"   error %@, %@", er, er.userInfo);
                                                  }
                                              }];
 }