Mac NSDocument-based application with document packages that saves very slowly

So, after I figured it out a bit, I realized that when I use the package for my document in an application based on NSDocument, do I have to write the whole set every time I want to save it? This is where the problem arises because I am adding large video files to the document.

Is there any way around this without throwing NSDocument?

+4
source share
2 answers

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 { // Read the contents of file wrapper // … [self setDocumentFileWrapper:fileWrapper]; return YES; } 

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

+10
source

I know this was answered, but as a reference, if you look at the Packaged Document sample, you will see an option that works without having to maintain the changed flag for each instance variable.

Main idea:

  • If the model variable changes, remove its corresponding file wrapper from the main file wrapper
  • When creating a file wrapper in fileWrapperOfType:… add only those that are missing (i.e. have been updated)
+4
source

Source: https://habr.com/ru/post/1482967/


All Articles