Does NSFileWrapper load everything into memory?
Asked Answered
J

2

7

Lets say I have an NSFileWrapper directory. This directory is made up of several levels of directories and files. Some of the files are large. Are all these files loaded into memory, or are they lazily loaded?

If they are loaded into memory, are there any alternatives to NSFileWrapper with similar functionality that won't load files into memory? Something I can hook into UIDocument?


This is for a document based application, which uses UIDocument's that are synced with iCloud. A document can have images and videos embedded inside it. Each image/video has a preview image (thumbnail) that is shown in an HTML document. The full size images or videos shouldn't be loaded into memory, but rather loaded on demand.

I also need a way to add a resource without loading it into memory. Something like "initWithAsset:(ALAsset *)" would be ideal.

Jhansi answered 29/11, 2012 at 8:20 Comment(0)
F
7

It's not totally clear from the documentation, but I'm 99% positive that NSFileWrapper will memory-map everything. The main use case for NSFileWrapper is to embed files inside documents, where you'd presumably need access to said file at all times.

What are you trying to use the file wrapper for? I assume if you're mapping an entire directory it's not necessarily to embed media inside a document, but perhaps I'm mistaken. If you maybe talk a bit more about your use case, as that will influence what alternatives you might go for.

Floribunda answered 29/11, 2012 at 10:19 Comment(3)
I ended up writing my own wrapper class that doesn't load anything into memory. I overloaded the writeContents:andAttributes:safelyToURL:forSaveOperation:error: and readFromURL:error: methods in UIDocument to add support for my custom object.Jhansi
@Jhansi I believe there has been a confusion. Memory mapped files in fact do mean lazy loading and are brought into active memory by pages. Also, if you retain a pointer to the original directory tupe NSFileWrapper, it will perform incremental save.Figured
Is it still the same in 2020?Improve
G
10

I've made an app a while ago that generates a video. This video was then saved to a specific file format using a UIDocument subclass.

The only way to make the app not run out of memory while executing contentsForType:error: was to output the video to a file in the tmp dir and init the filewrapper with the url to the video with NSFileWrapperReadingWithoutMapping-option to prevent it from loading the video to memory and just copy in the file.

- (id)contentsForType:(NSString *)typeName error:(NSError **)outError {
    if (self.fileWrapper == nil) {
        self.fileWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil];
    }

        if (self.videoURL != nil) {

            NSError *fileReadError;
            NSFileWrapper *videoFileWrapper = [[NSFileWrapper alloc] initWithURL:self.videoURL options:NSFileWrapperReadingWithoutMapping error:&fileReadError];

            if(fileReadError){
                NSLog(@"File read error: %@", [fileReadError localizedDescription]);
            }else {
                [videoFileWrapper setPreferredFilename:@"video.mov"];
                [self.fileWrapper addFileWrapper:videoFileWrapper];
            }        

        }
//...
}
Greenberg answered 27/2, 2014 at 11:1 Comment(4)
Hi JoriDor, I have the exact same problem you have; storing videos in an NSFileWrapper. I've tried your tmp solution using initWithURL:options:error: method, but RAM usage is still very high after contentsForType:error: returns. Did you find a solution for that?Derwin
Hi, Rengers, should the above not help, you can exclude the video from the bundle definition. When my class writes the bundle, I copy the file into the bundle. When reading, I just search for a video file in the bundle and use an NSURL to point to it.Greenberg
Tnx JoriDor. Although it feels a bit like a hack, it looks like it would fix the problem.Derwin
Rangers, there is a way to do this the clean way, depending on how much time you have, and that is to create your custom FileWrapper. There are a couple of them on the internet, one of them is LSWrapper by Luke Scott. See github.com/lukescott/LSFileWrapperGreenberg
F
7

It's not totally clear from the documentation, but I'm 99% positive that NSFileWrapper will memory-map everything. The main use case for NSFileWrapper is to embed files inside documents, where you'd presumably need access to said file at all times.

What are you trying to use the file wrapper for? I assume if you're mapping an entire directory it's not necessarily to embed media inside a document, but perhaps I'm mistaken. If you maybe talk a bit more about your use case, as that will influence what alternatives you might go for.

Floribunda answered 29/11, 2012 at 10:19 Comment(3)
I ended up writing my own wrapper class that doesn't load anything into memory. I overloaded the writeContents:andAttributes:safelyToURL:forSaveOperation:error: and readFromURL:error: methods in UIDocument to add support for my custom object.Jhansi
@Jhansi I believe there has been a confusion. Memory mapped files in fact do mean lazy loading and are brought into active memory by pages. Also, if you retain a pointer to the original directory tupe NSFileWrapper, it will perform incremental save.Figured
Is it still the same in 2020?Improve

© 2022 - 2024 — McMap. All rights reserved.