3

I have UIDocument in iCloud ubiquitous container and I need to append data to file while saving document. I override readFromURL:: and writeContents::::: method according UIDocument documentation:

-(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;
}

Accessor block has different newURL, for example:

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::] failed, because newURL file dosn't exists and I can't append data, only create file with all document's content.

Document editing code:

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 exists in ubiquitous container at url and document has Normal state.

How I can do incremental writing in this case? Whats wrong?

Vitaly Kudrin
  • 231
  • 1
  • 2
  • 9

1 Answers1

0

After changing data in your UIDocumnet you can use:

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

Not sure, it's right or not but it works in my app. If it's wrong, correct me please somebody.

You may need to overwrite this method in your subclass of UIDocumnet:

- (id) contentsForType:(NSString *)typeName error:(NSError **)outError
Volodymyr B.
  • 3,369
  • 2
  • 30
  • 48
  • I use `[UIDocument saveToURL::]` for creating document. If document already exists I use autosaving via `[UIDocument updateChangeCount:], and `[UIDocument closeWithCompletionHandler:]` call saving automatically. – Vitaly Kudrin Jan 29 '14 at 10:27
  • I have own `- (id) contentsForType:(NSString *)typeName error:(NSError **)outError` and simply return non-empty NSData with archived document content – Vitaly Kudrin Jan 29 '14 at 10:29