2

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

Community
  • 1
  • 1
kroger
  • 448
  • 3
  • 10

1 Answers1

3

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);
                                                  }
                                              }];
 }
Duncan Groenewald
  • 8,496
  • 6
  • 41
  • 76
  • Coordinator allows to read and write at the same time, you could request to read and write at the same time using the same container URL, then simply read list of files and wipe them at the same time. – pronebird Nov 23 '16 at 15:39