One of the benefits of using document packages is that you don’t have to write everything every time you save. You must add the documentFileWrapper property to your NSDocument subclass, and when the document architecture is read in the document package, you must keep the NSFileWrapper reference in this property, and you must also keep track of what has changed. For example, aAssuming youre, saving a text file and a video file in a document package:
@interface MyDocument () @property (nonatomic, copy) NSString *text; @property (nonatomic, assign) bool textHasChanged; @property (nonatomic, copy) NSData *videoData; @property (nonatomic, assign) bool videoHasChanged; @property (nonatomic, strong) NSFileWrapper *documentFileWrapper; @end
and
- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError **)outError {
If a document package was read from disk, documentFileWrapper stores a link to this package. If his new document documentFileWrapper is nil .
When saving a document, reuse documentFileWrapper and write only files that need to be saved. If the document has not yet been saved (new document), documentFileWrapper is nil , you need to create it:
- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError { if ([self documentFileWrapper] == nil) { NSFileWrapper *documentFileWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:@{}]; [self setDocumentFileWrapper:documentFileWrapper]; } NSDictionary *fileWrappers = [[self documentFileWrapper] fileWrappers]; NSFileWrapper *textFileWrapper = [fileWrappers objectForKey:@"text.txt"]; NSFileWrapper *videoFileWrapper = [fileWrappers objectForKey:@"video.mp4"]; if ((textFileWrapper == nil && [self text] != nil) || [self textHasChanged]) { if (textFileWrapper != nil) [documentFileWrapper removeFileWrapper:textFileWrapper]; if ([self text] != nil) { NSData *textData = [[self text] dataUsingEncoding:NSUTF8StringEncoding]; [documentFileWrapper addRegularFileWithContents:textData preferredFileName:@"text.txt"]; } } if ((videoFileWrapper == nil && [self videoData] != nil) || [self videoHasChanged]) { if (videoFileWrapper != nil) [documentFileWrapper removeFileWrapper:videoFileWrapper]; if ([self videoData] != nil) [documentFileWrapper addRegularFileWithContents:[self videoData] preferredFileName:@"video.mp4"]; } return documentFileWrapper; }
In the above code, a document package (file shell) is created only if it does not already exist. In other words, it is created only if the document is new and has not yet been saved. After creating the package, its link is saved in documentFileWrapper .
Next, we check whether we need to write a text file. This is written if: * either there is no text file (probably because its a new package), and we have the actual text to write; * or if the text has been changed.
We do the same for the video file.
Please note that if a document is downloaded from disk or saved at least once, the video file is added to the package (and the previous video file, if any, is deleted from the package) only if the video data has been changed.
NB: this answer assumes ARC and automatic synthesis of properties (ivar names with underscore prefix).