gpt4 book ai didi

ios - 文件从NSLibraryDirectory中消失

转载 作者:行者123 更新时间:2023-12-01 15:23:45 26 4
gpt4 key购买 nike

我使用以下方法将其存储在iOS应用程序的“库”目录中。最后,我可以调用[MyClass dataDirectory]进行文件处理,一切都很好。但是,我最近发现,有些文件似乎神秘地从该目录中消失了。根据the documentation,情况并非如此。这是存储持久文件的安全场所吗?

该目录的控制台输出是:~/var/mobile/Containers/Data/Application/{id}/Library/Data

+ (NSString*)libraryDirectory
{
return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
}

+ (NSString*)dataDirectory
{
NSString* dir = [[self libraryDirectory] stringByAppendingPathComponent:@"Data"];
BOOL isDir=NO;
NSError * error = nil;
NSFileManager *fileManager = [NSFileManager new];

if (![fileManager fileExistsAtPath:dir isDirectory:&isDir] && isDir)
{

[[NSFileManager defaultManager] createDirectoryAtPath:dir
withIntermediateDirectories:YES
attributes:nil
error:&error];
}

[self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:dir isDirectory:YES]];

if (error != nil) {
DDLogError(@"Fatal error creating ~/Library/Data directory: %@", error);
}
return dir;
}

和skip方法:
+ (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
if ([[NSFileManager defaultManager] fileExistsAtPath:[URL path]])
{
assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);

NSError *error = nil;
BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
forKey: NSURLIsExcludedFromBackupKey error: &error];
if(!success){
DDLogError(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
}
return success;
}
return YES;
}

最佳答案

在您发布的代码中,第一个问题在这里:if (![fileManager fileExistsAtPath:dir isDirectory:&isDir] && isDir)在评估该值时,isDir将默认为NO,如果文件不存在或不是目录,则将其设置为NO。这将阻止创建目录。删除&& isDir或更改为|| !isDir以获取所需的逻辑。
现在开始您的原始问题:
这(NSLibraryDirectory的子目录)是存储持久文件的安全场所吗?
是的。默认情况下会备份NSLibraryDirectory。为了遵守iOS Data Storage Guidelines,应用程序不应在该位置存储用户创建的数据,但在此处存储应用程序数据是安全的。 NSApplicationSupportDirectory是通常在NSLibraryDirectory内的目录,并且是存储此类数据的首选位置。该位置中的数据将被备份,并将在应用程序和操作系统更新期间迁移。
iOS Data Storage GuidelinesFile System Programming GuideApp Programming Guide for iOS都提供有关将文件放置在何处以及如何从标准文件系统位置备份文件的指南。
除非这些文件的NSURLIsExcludedFromBackupKey/kCFURLIsExcludedFromBackupKey资源元数据值已更改。然后,它变得更加复杂。
“从备份中排除”的文件
通常,如果可以备份Documents目录之外的文件,则系统会假定它也可以在空间不足或其他情况下清除该文件。这就是将文件上的NSURLIsExcludedFromBackupKey设置为YES的原因,即使文件在低存储条件下也可以持久保存。如果您的应用程序将文件的NSURLIsExcludedFromBackupKey设置为YES,则您的应用程序将对该文件的生命周期负责。
这里要注意的是,备份过程和清除过程没有遵循相同的逻辑。 Apple的文档表明,出于控制备份行为的目的,可以在目录上设置NSURLIsExcludedFromBackupKey。该目录的子级将有效地继承该资源值(实际上,这可能不准确)。但是,清除过程似乎没有相同的行为。它可能不会检查父目录的备份排除项并将其应用于子目录,因此,如果未明确设置NSURLIsExcludedFromBackupKey的文件可能会被清除。
这变得更加复杂。如果您要阅读documentation for the constant NSURLIsExcludedFromBackupKey,则会看到:

Some operations commonly made to user documents cause this property to be reset to false; consequently, do not use this property on user documents.


实际上,这不仅适用于用户文档。例如,如果要对文件执行原子写入,例如: [thing writeToURL:URL atomically:YES encoding:NSUTF8StringEncoding error:&error]如果在写入之前 URL处的文件的 NSURLIsExcludedFromBackupKey设置为YES,则现在看来将其设置为NO。像这样的原子写入将首先创建一个临时文件,对其进行写入,然后用新文件替换原始文件。这样做不会保留文件和URL资源标志。原始文件设置了 NSURLIsExcludedFromBackupKey资源值,而现在在同一位置的新创建的文件没有。这只是一个例子。许多Foundation API隐式地执行原子写操作。
在某些情况下,情况变得更加复杂。更新应用程序后,它将使用新的应用程序容器路径安装到新位置。旧应用程序容器内的数据将被迁移。对于在更新过程中可能迁移或可能不迁移的内容,几乎没有保证。它可能是所有事物,可能只是一些事物。特别是,没有关于如何处理带有 NSURLIsExcludedFromBackupKey资源属性标记的文件或目录的指南。实际上,似乎这些文件通常是最不可能迁移的文件,并且在迁移文件时,很少保留 NSURLIsExcludedFromBackupKey属性。
操作系统更新也是一个问题。从历史上看,空中更新一直存在问题,并导致 NSURLIsExcludedFromBackupKey资源属性被有效清除或忽略。 “重大”操作系统更新将清除设备并从备份中还原-等同于迁移到新硬件。标有 NSURLIsExcludedFromBackupKey资源属性的文件将不会被迁移,应用程序将不得不重新创建它们。
更新方案在 TechNote 2285: Testing iOS App Updates中进行了描述
因此,在使用 NSURLIsExcludedFromBackupKey时,通常最好在每次访问时都设置该值,并且一如既往应通过 File Coordination APIs进行设置(除非您要写入共享组容器,这是一组完全不同的问题)。如果 NSURLIsExcludedFromBackupKey资源属性值丢失,则可以随时清除文件。理想情况下,应用程序不应依赖于 NSURLIsExcludedFromBackupKey或操作系统如何(或不可以!)来处理它,而应设计为可以按需重新创建数据。这并非总是可能的。
从您的问题和发布的代码中可以清楚地看出,您在某种程度上依赖 NSURLIsExcludedFromBackupKey来确保文件具有应用程序控制的生存期。从上面的内容可以看出,情况并非总是如此:在很多常见的情况下,资源属性值可能消失,并且文件也随之消失。
还值得注意的是,NSFileProtection属性以相同的方式工作,并且可以在相同的场景(以及更多情况)下消失。
TL; DR;我应该怎么办?
根据您的问题,代码和所看到的行为的描述:
  • 在包含要保存的文件的目录上设置NSURLIsExcludedFromBackupKey值可能不足以防止其被清除。在对实际文件的每次访问上设置NSURLIsExcludedFromBackupKey而不是仅设置父目录是明智的。还应尝试确保在对文件进行任何写入之后设置此资源值,尤其是通过可能正在执行原子写入的高级API等进行设置。
  • 所有NSFileManager和文件读取/写入操作应使用文件协调。即使在单线程应用程序中,也会有其他进程与“您的”文件进行交互。诸如守护程序之类的进程在空间不足的情况下运行备份或清除文件。在-fileExistsAtPath:-setResourceValue:forKey:error:之间,另一个进程可能会更改,删除或移动文件及其属性。 -setResourceValue:forKey:error:实际上在许多不执行任何操作的情况下(例如文件不存在)将返回YES并且没有错误。
  • 标有NSURLIsExcludedFromBackupKey的文件和目录是应用程序的管理职责。应用程序仍应在适当的时候清除这些文件或其内容,或设置其增长限制。如果查看设备上每个应用程序的磁盘使用情况信息,则可能会猜到某些未正确执行此操作的应用程序的名称。
  • 测试更新方案,如TechNote 2285: Testing iOS App Updates中所述。经常。理想情况下,iOS Simulator具有类似于模拟内存警告的“模拟磁盘空间不足”的功能,但目前还没有。
  • 如果可能,请更改应用程序逻辑以重新创建这些文件。
  • 关于ios - 文件从NSLibraryDirectory中消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27216189/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com