У меня есть приложение на основе NSDocument, которое использует файловые завесы для сохранения и загрузки своих данных. Документ может иметь все виды ресурсов, поэтому я не хочу загружать все в память. Я мог бы сделать что-то принципиально неправильное, но как только я сменил один (внутренний) файл, а затем сохранил, я не могу прочитать файл, который не был загружен в память.NSFileWrapper, ленивая загрузка и сохранение
Я выделил соответствующий код в отдельный проект, чтобы воспроизвести это поведение, и получаю те же результаты. Основной поток таков:
- Загружаю существующий документ с диска. Основной файл-файл является файловым файлом каталога (я буду называть это основным), содержащим два других файлообмена (sub1 и sub2). В этот момент загружены два внутренних файла: , а не.
- Когда пользователь хочет отредактировать sub1, он загружается с диска.
- Пользователь сохраняет документ
Если пользователь хочет изменить другой файл (sub2), он не может загрузить. Ошибка, которая появляется:
-[NSFileWrapper regularFileContents] tried to read the file wrapper's contents lazily but an error occurred: The file couldn’t be opened because it doesn’t exist.
Вот соответствующий код в моем проекте:
Этот код может быть проще читать в этом суть: https://gist.github.com/bob-codingdutchmen/6869871
#define FileName01 @"testfile1.txt"
#define FileName02 @"testfile2.txt"
/**
* Only called when initializing a NEW document
*/
-(id)initWithType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
self = [self init];
if (self) {
self.myWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil];
NSLog(@"Initializing new document...");
NSString *testString1 = @"Lorem ipsum first sub file";
NSString *testString2 = @"This is the second sub file with completely unrelated contents";
NSFileWrapper *w1 = [[NSFileWrapper alloc] initRegularFileWithContents:[testString1 dataUsingEncoding:NSUTF8StringEncoding]];
NSFileWrapper *w2 = [[NSFileWrapper alloc] initRegularFileWithContents:[testString2 dataUsingEncoding:NSUTF8StringEncoding]];
w1.preferredFilename = FileName01;
w2.preferredFilename = FileName02;
[self.myWrapper addFileWrapper:w1];
[self.myWrapper addFileWrapper:w2];
}
return self;
}
-(NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
// This obviously wouldn't happen here normally, but it illustrates
// how the contents of the first file would be replaced
NSFileWrapper *w1 = [self.myWrapper.fileWrappers objectForKey:FileName01];
[self.myWrapper removeFileWrapper:w1];
NSFileWrapper *new1 = [[NSFileWrapper alloc] initRegularFileWithContents:[@"New file contents" dataUsingEncoding:NSUTF8StringEncoding]];
new1.preferredFilename = FileName01;
[self.myWrapper addFileWrapper:new1];
return self.myWrapper;
}
-(BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
self.myWrapper = fileWrapper;
return YES;
}
- (IBAction)button1Pressed:(id)sender {
// Read from file1 and show result in field1
NSFileWrapper *w1 = [[self.myWrapper fileWrappers] objectForKey:FileName01];
NSString *string1 = [[NSString alloc] initWithData:w1.regularFileContents encoding:NSUTF8StringEncoding];
[self.field1 setStringValue:string1];
}
- (IBAction)button2Pressed:(id)sender {
// Read from file2 and show result in field2
NSFileWrapper *w2 = [[self.myWrapper fileWrappers] objectForKey:FileName02];
NSString *string2 = [[NSString alloc] initWithData:w2.regularFileContents encoding:NSUTF8StringEncoding];
[self.field2 setStringValue:string2];
}
Нижние два метода предназначены только для обновления пользовательского интерфейса, чтобы я мог видеть, что происходит.
Чтобы изменить содержимое файла, я удаляю существующий fileWrapper и добавляю новый. Это единственный способ изменить содержимое файла и способ, которым я это видел в других ответах SO.
Когда документ загружается с диска, я держу fileWrapper вокруг, так что я могу использовать его (так называемый myWrapper в коде выше)
Документах Apple, говорят, что NSFileWrapper поддерживает отложенную загрузку и поэтапное сохранение, поэтому я предполагаю, что у моего кода есть некоторые фундаментальные недостатки, которые я не вижу.
Поддерживает ли ваш документ управление версиями? –
Я не уверен, поэтому я не думаю :) Я не сделал ничего, чтобы поддержать его. Это изменит что-нибудь? Я рассмотрю это позже. –
Поскольку я использую установку NSDocument, я поддерживал управление версиями. Я пытался отключить его, но результат тот же –