Защо записването на файлове в NSDocument създава версии на същия файл със странни знаци в името им?

Работя върху приложение, базирано на NSDocument, чийто тип документ е пакетен пакет, който съдържа куп файлове. Запазвам го така:

- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError
{
    if (!self.documentFileWrapper) {
        NSFileWrapper *documentFileWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil];
        [self setDocumentFileWrapper:documentFileWrapper];
    }

    NSFileWrapper *defaultWrapper = [self.documentFileWrapper.fileWrappers objectForKey:@"default"];
    if (!defaultWrapper) {
        defaultWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil];
        [defaultWrapper setPreferredFilename:@"someFile.ext"];
        [self.documentFileWrapper addFileWrapper:defaultWrapper];
    }

    [defaultWrapper addRegularFileWithContents: ... some computed content for the file ... preferredFilename:@"someFile.ext"];

    return self.documentFileWrapper;
}

С други думи, в пакета създайте папка „default“ и запазете „someFile.ext“ в нея с малко съдържание.

Сега проблемът. Когато погледна какво всъщност е запазено на диска, виждам това:

екранна снимка

Всеки път, когато запазя файла, обвивката на NSDocument изглежда създава някакво версионно копие на ресурса. Не искам версионните клонинги, искам само ванилия файл с най-новото съдържание.

Откъде идват ресурсите с версии? Какво става тук? Има ли документ, който трябва да прочета?


person Jaanus    schedule 26.02.2014    source източник
comment
+ (BOOL)preservesVersions Върната стойност ДА, ако получаващият подклас на NSDocument поддържа версии; иначе НЕ.   -  person Oleg Sobolev    schedule 03.03.2014
comment
Е, поне мога да потвърдя наличието на допълнителните файлове, които изброявате, дори когато + (BOOL)preservesVersions върне НЕ, независимо какво връща + (BOOL)autosavesInPlace. Промяната на връщаните стойности на тези две функции засяга активираните опции в менюто, така че те се се запитват. Ще ви уведомя, ако намеря още нещо.   -  person Erhannis    schedule 08.03.2014


Отговори (2)


Добре, мисля, че разбрах. Както се оказа, всъщност не беше проблем с версията. Изглежда, че просто сте добавяли нов файл всеки път. Първо, няколко бележки.

  1. Изглежда не създавате файл в пакет, а „директория, съдържаща файл“ в пакет. Това ли възнамерявахте да направите?
  2. Изглежда, че ако директорията "default" не съществува, създавате и използвате директория "someFile.ext", което означава, че следващия път създава нова директория със странен префикс. Виждам обаче от вашата екранна снимка, че вече имате директория „по подразбиране“, което означава, че това не е ваш проблем.

Сега вашият действителен проблем: според тази документация, addRegularFileWithContents създава нов файл с предпочитаното от вас име на файл, освен ако директорията (defaultWrapper) вече съдържа файл с това име (основно). Ако вече има, той създава нов файл с префикс. addRegularFileWithContents връща идентифициращ низ, отнасящ се до създадения NSFileWrapper (мисля, че това е името на файла).

И така, това, което се случва, е, че всеки път, когато отидете да запазите файла, той вижда, че вече има файл с това име, и създава нов с префикс. Един от начините за решаване на това е да запазите NSString, върнат от addRegularFileWithContents, след което, когато отидете да запазите, проверявате defaultWrapper и премахвате NSFileWrapper, свързан със съхранения NSString, ако има такъв, и след това добавяте файла както обикновено. Промених вашия код, както следва:

@interface TestDocument () // Relevant part of my test class.  Note `wrapperFileName`.

@property (nonatomic, strong) NSFileWrapper *documentFileWrapper;
@property (nonatomic, strong) NSString *wrapperFileName;

@end



- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError
{
    if (!self.documentFileWrapper) {
        NSFileWrapper *documentFileWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil];
        [self setDocumentFileWrapper:documentFileWrapper];
    }

    NSFileWrapper *defaultWrapper = [self.documentFileWrapper.fileWrappers objectForKey:@"default"];
    if (!defaultWrapper) {
        defaultWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil];
        [defaultWrapper setPreferredFilename:@"default"];
        [self.documentFileWrapper addFileWrapper:defaultWrapper];
    } else if (self.wrapperFileName) {
        [defaultWrapper removeFileWrapper:[[defaultWrapper fileWrappers] objectForKey:self.wrapperFileName]];
    }

    self.wrapperFileName = [defaultWrapper addRegularFileWithContents:[@"blah blah" dataUsingEncoding:NSUTF8StringEncoding] preferredFilename:@"someFile.txt"];
    return self.documentFileWrapper;
}
  1. Промених предпочитаното име на файл на defaultWrapper да бъде "по подразбиране", както подозирам, че сте възнамерявали.
  2. Добавих блок if, който премахва предварително запазения файл, ако е съществувал такъв.
  3. Накарах го да съхранява името на файла на новия NSFileWrapper, за използване следващия път в #2.

След тези промени програмата демонстрира това, което според мен е поведението, което очаквате: една директория, съдържаща един файл, дори след многократно записване. Имайте предвид, че това беше вярно дори когато preservesVersions върна YES. Не съм сигурен къде съхранява версиите си, но не ги видях.

person Erhannis    schedule 07.03.2014
comment
Благодаря, както се казва в началото, „Изглежда, че просто сте добавяли нов файл всеки път.“ беше правилен, така че това беше доста проста грешка от моя страна. Мислех, че добавянето на файл със същото име го презаписва, но очевидно не, така че трябва сам да премахна дубликатите. / „Изглежда не създавате файл в пакет, а „директория, съдържаща файл“ в пакет. Това ли възнамерявахте да направите?“ -- да. - person Jaanus; 10.03.2014

Бихте могли да приложите -writeSafely... така че да извиква направо до -writeToURL:... Приложете -writeToURL:... така че да извиква -fileWrapperOfType:... и след това да го запише в URL адреса атомично

т.е. ще поемете отговорността за атомарните запазвания, като накарате NSFileWrapper да го направи. По този начин обвивката трябва внимателно да проследява къде наистина свършват файловете.

Източник

person Danish Iqbal    schedule 09.03.2014