Как выполнять инкрементную запись для UIDocument в iCloud?

У меня есть UIDocument в универсальном контейнере iCloud, и мне нужно добавить данные в файл при сохранении документа. Я переопределяю методы readFromURL:: и writeContents::::: в соответствии с документацией UIDocument:

-(BOOL) writeContents:(id)contents toURL:(NSURL*)url forSaveOperation:(UIDocumentSaveOperation)saveOperation originalContentsURL:(NSURL*)originalContentsURL error:(NSError *__autoreleasing *)outError
{
    NSFileCoordinator* coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:self];
    NSError* error = nil;
    [coordinator coordinateWritingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {
        NSData* data = contents; //correct, non-empty NSData

        ///[data writeToFile:newURL :] works, but overwrite original file

        NSOutputStream* stream =[[NSOutputStream alloc] initWithURL:newURL append:YES];
        if (stream)
        {
            NSInteger written = [stream write:data.bytes maxLength:data.length];
            if (written != data.length)
            {
                //failed here, written == -1
                NSLog(@"Write data to UIDocument failed: %@, error: %@", newURL, stream.streamError);
            }
        }
        else
        {
            NSLog(@"Write data to iCloudDocument failed: %@", newURL);
        }
    }];

    if (error)
    {
        NSLog(@"Coordinated write failed %@, error: %@", url, error);
        *outError = error;
    }

    return error == nil;
}

Блок-аксессор имеет другой новый URL-адрес, например:

url: file:///private/var/mobile/Library/Mobile%20Documents/XXXXXXX~com~test~test/test.doc

newURL: file:///private/var/mobile/Applications/5631D484-7661-4E9E-A342-B25297FC0E18/tmp/(A%20Document%20Being%20Saved%20By%20test%20)/test.doc.

[stream write::] не удалось, потому что newURL файл не существует, и я не могу добавить данные, а только создать файл со всем содержимым документа.

Код редактирования документа:

NSURL* url = [self.containerURL URLByAppendingPathComponent:kCloudDocumentName];

MyDocument* document = [[MyDocument alloc] initWithFileURL:url];
[document openWithCompletionHandler:^(BOOL success) {
    if (success)
    {
        //update some document data
        [self updateData:document completion:nil];

        [document closeWithCompletionHandler:^(BOOL success) {
            //failed here!
        }];

    }
}];

MyDocument существует в универсальном контейнере по адресу url, и документ находится в нормальном состоянии.

Как я могу писать в этом случае? Что случилось?


person Vitaly Kudrin    schedule 29.01.2014    source источник
comment
Я тоже столкнулся с той же проблемой. Любое решение?   -  person Shyam    schedule 29.03.2019


Ответы (1)


После изменения данных в вашем UIDocumnet вы можете использовать:

-[UIDocumnet saveToURL:UIDocumnet.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:nil];

Не уверен, правильно это или нет, но в моем приложении он работает. Если не так, поправьте меня, пожалуйста, кто-нибудь.

Возможно, вам придется перезаписать этот метод в своем подклассе UIDocumnet:

- (id) contentsForType:(NSString *)typeName error:(NSError **)outError
person Volodymyr B.    schedule 29.01.2014
comment
Я использую [UIDocument saveToURL::] для создания документа. Если документ уже существует, я использую автосохранение с помощью автоматического сохранения вызова [UIDocument updateChangeCount:], and [UIDocument closeWithCompletionHandler:] `. - person Vitaly Kudrin; 29.01.2014
comment
У меня есть собственный - (id) contentsForType:(NSString *)typeName error:(NSError **)outError, и я просто возвращаю непустые NSData с заархивированным содержимым документа - person Vitaly Kudrin; 29.01.2014