Search code examples
ioscore-dataicloud

How to Delete an iCloud ubiquity containers on the iPhone?


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).


Solution

  • 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);
                                                      }
                                                  }];
     }