Rename an iCloud document

微笑、不失礼 提交于 2021-02-09 05:04:41

问题


The problem

What I have so far is code that creates a new local file and deletes the iCloud file.

Is it possible to rename an iCloud document, so that it stays in iCloud?

GarageBand can do it. It's possible to rename an iCloud song. After the rename is done, the song is still in iCloud. However GarageBand is an Apple app, so it may use private apis.

My current code:

- (void)moveFrom:(NSURL*)sourceURL
          moveTo:(NSString*)destinationName
      completion:(void (^)())completion
{
    MyDocument *document = [[MyDocument alloc] initWithFileURL:sourceURL];
    [document openWithCompletionHandler:^(BOOL success)
    {
        NSURL *fileURL = [self.localRoot URLByAppendingPathComponent:destinationName];
        DLog(@"Create %@", fileURL);
        [document saveToURL:fileURL
           forSaveOperation:UIDocumentSaveForCreating
          completionHandler:^(BOOL success)
        {
            NSLog(@"Saved %@", fileURL);
            [document closeWithCompletionHandler:^(BOOL success) {
                // Delete the old document from a secondary thread
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^()
                {
                    NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
                    [fileCoordinator coordinateWritingItemAtURL:sourceURL
                                                        options:NSFileCoordinatorWritingForDeleting
                                                          error:nil
                                                     byAccessor:^(NSURL* writingURL) {
                        NSFileManager* fileManager = [[NSFileManager alloc] init];
                        [fileManager removeItemAtURL:writingURL error:nil];
                        DLog(@"Deleted %@", sourceURL);
                        completion();
                    }];
                });
            }];
        }];
    }];
}

Update: Still no luck

I have found out that -setUbiquitous:itemAtURL:destinationURL:error: cannot be used for renaming documents.

If I invoke [setUbiquitous:NO itemAtURL:oldLocalURL destinationURL:newLocalURL error:&error] on an already local file, then:

Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)" UserInfo=0x1fdf6730 {NSURL=file://localhost/var/mobile/Applications/4BABA000-B100-49FC-B928-B0F403FC75FF/Documents/LocalDrawing.td2/, NSUnderlyingError=0x20940e80 "The operation couldn’t be completed. (LibrarianErrorDomain error 2 - Cannot disable syncing on a unsynced item.)"}

If I invoke [setUbiquitous:YES itemAtURL:oldCloudURL destinationURL:newCloudURL error:&error] on an already cloud file, then:

Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)" UserInfo=0x208e9820 {NSURL=file://localhost/var/mobile/Library/Mobile%20Documents/22DR89XVRF~com~opcoders~triangle-draw/Documents/CloudDrawing.td2/, NSUnderlyingError=0x208d45b0 "The operation couldn’t be completed. (LibrarianErrorDomain error 2 - Cannot enable syncing on a synced item.)"}

Thus -setUbiquitous:itemAtURL:destinationURL:error: cannot be used for renaming documents.


回答1:


I have finally solved it. This is my code so far:

- (void)_moveURL:(NSURL*)sourceURL
         destURL:(NSURL*)destinationURL
         success:(void (^)())successBlock
         failure:(void (^)(NSError *))failureBlock
{
    NSParameterAssert(sourceURL);
    NSParameterAssert(destinationURL);
    NSParameterAssert(successBlock);
    NSParameterAssert(failureBlock);

    // Do the actual renaming
    __block NSError *moveError = nil;
    __block BOOL moveSuccess = NO;
    void (^accessor)(NSURL*, NSURL*) = ^(NSURL *newURL1, NSURL *newURL2) {
        NSFileManager *fileManager = [[NSFileManager alloc] init];
        moveSuccess = [fileManager moveItemAtURL:sourceURL toURL:destinationURL error:&moveError];
    };

    // Coordinate renaming
    NSError *coordinatorError = nil;
    NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
    [coordinator coordinateWritingItemAtURL:sourceURL
                                    options:NSFileCoordinatorWritingForMoving
                           writingItemAtURL:destinationURL
                                    options:NSFileCoordinatorWritingForReplacing
                                      error:&coordinatorError
                                 byAccessor:accessor];
    if (moveSuccess) {
        successBlock();
        return;
    }
    if (moveError) {
        failureBlock(moveError);
        return;
    }
    if (coordinatorError) {
        failureBlock(coordinatorError);
        return;
    }
    NSAssert(NO, @"should not happen");
}



回答2:


There is an easier way to rename item at any given URL, including iCloud URLs.

url.setResourceValue(newName, forKey: NSURLNameKey)

I am using this in my cocoa app's production code.

Edit: In Swift 5, this looks a little different, but still works well:

var resourceValues = URLResourceValues()
resourceValues.name = newName
try previousFileURL.setResourceValues(resourceValues)


来源:https://stackoverflow.com/questions/14358504/rename-an-icloud-document

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!