bra*_*ipt 3 objective-c ios nsdocumentdirectory nslibrarydirectory
我将一些文件存储在iOS应用程序的Library目录中,使用以下方法构建它.最后,我可以调用[MyClass dataDirectory]我的文件处理,一切都很顺利.然而,我最近发现,一些文件似乎神秘地消失在这个目录之外.根据文件,情况并非如此.这是存储持久文件的安全位置吗?
该目录的控制台输出是: ~/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;
}
Run Code Online (Sandbox Code Playgroud)
和跳过方法:
+ (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;
}
Run Code Online (Sandbox Code Playgroud)
que*_*ish 23
在您发布的代码中,第一个问题出现在:
if (![fileManager fileExistsAtPath:dir isDirectory:&isDir] && isDir)
在评估它时,isDir将默认为NO,如果文件不存在或不是目录,则将设置为NO.这将阻止创建目录.删除&& isDir或更改为|| !isDir获得所需的逻辑.
现在回答你原来的问题:
是.NSLibraryDirectory默认情况下备份.要遵守iOS数据存储指南,应用程序不应将用户创建的数据存储在该位置,但它是存储应用程序数据的安全位置.NSApplicationSupportDirectory是一个目录,通常位于NSLibraryDirectory,并且是存储此类数据的首选位置.将备份该位置中的数据,并将在应用程序和操作系统更新期间迁移.
在iOS的数据存储准则,文件系统编程指南,以及应用程序编程指南适用于iOS都提供在何处放置文件的指导,以及它们将如何从标准文件系统位置备份.
除非这些文件的NSURLIsExcludedFromBackupKey/ kCFURLIsExcludedFromBackupKey资源元数据值已更改.然后它变得更加复杂.
通常,如果可以备份Documents目录之外的文件,系统会假定它也可以在低空间或其他条件下清除它.这就是为什么NSURLIsExcludedFromBackupKey在文件上设置为YES允许文件即使在低存储条件下也能保持原样的原因.如果您的应用程序将NSURLIsExcludedFromBackupKey文件设置为YES,则您的应用程序将承担该文件的生命周期.
这里的问题是备份过程和清除过程不遵循相同的逻辑.Apple的文档表明,为了控制备份行为,可以NSURLIsExcludedFromBackupKey在目录上进行设置.该目录的子级将有效地继承该资源值(实际上,这可能不准确).但是,清除过程似乎没有相同的行为.它可能无法检查父目录的备份排除并将其应用于子目录,因此如果文件没有NSURLIsExcludedFromBackupKey明确设置,则可能会清除它.
这变得更加复杂.如果您要阅读常量 的文档,NSURLIsExcludedFromBackupKey您会看到:
通常对用户文档进行的一些操作会导致此属性重置为false; 因此,请勿在用户文档上使用此属性.
这实际上不仅适用于用户文档.例如,如果要对文件执行原子写操作,例如:
[thing writeToURL:URL atomically:YES encoding:NSUTF8StringEncoding error:&error]
如果该文件在URL已NSURLIsExcludedFromBackupKey写入前设置为YES,它现在似乎被设置为NO.像这样的原子写入将首先创建一个临时文件,写入该文件,并用新文件替换原始文件.这样做不会保留文件和URL资源标志.原始文件NSURLIsExcludedFromBackupKey设置了资源值,现在在同一位置新创建的文件没有.这只是一个例子; 许多Foundation API执行这样的原子写入.
有些情况会变得更加复杂.更新应用程序时,会将其安装到具有新应用程序容器路径的新位置.迁移旧应用程序容器内的数据.关于在更新过程中可能迁移或不迁移的内容的保证很少.它可能是一切,它可能只是一些东西.特别是没有关于如何NSURLIsExcludedFromBackupKey处理标有资源属性的文件或目录的指导.在实践中,似乎这些文件通常是最不可能迁移的文件,并且在迁移它们时,NSURLIsExcludedFromBackupKey很少保留该属性.
操作系统更新也是一个问题.历史上,Over-the-Air更新存在问题,并导致NSURLIsExcludedFromBackupKey资源属性被有效清除或忽略."主要"操作系统更新将清除设备并从备份恢复 - 这相当于迁移到新硬件.标记为NSURLIsExcludedFromBackupKeyresource属性的文件将不会迁移,应用程序将不得不重新创建它们.
TechNote 2285:测试iOS应用更新中描述了更新方案
因此,在使用NSURLIsExcludedFromBackupKey它时通常最好在每次访问时设置值,并且应始终通过文件协调API完成(除非您要写入共享组容器,这是一组完全不同的问题).如果NSURLIsExcludedFromBackupKey资源属性值丢失,则可以随时清除文件.理想情况下,应用程序不应该依赖于NSURLIsExcludedFromBackupKey操作系统可能(或可能不)处理它的方式,而应该设计为可以按需重建数据.这可能并不总是可能的.
从您的问题和您发布的代码中可以清楚地看出,您在某种程度上依赖于NSURLIsExcludedFromBackupKey确保您的文件具有应用程序控制的生命周期.正如您从上面所看到的,情况可能并非总是如此:有许多常见的情况,资源属性值可以消失,并且随之而来的是您的文件.
值得注意的是,NSFileProtection属性以相同的方式工作,并且可以在相同的场景中消失(还有一些).
根据您的问题,代码和您所看到的行为的描述:
NSURLIsExcludedFromBackupKey在包含您要保留的文件的目录上设置值可能不足以阻止它们被清除.设置NSURLIsExcludedFromBackupKey对实际文件的每次访问都是明智的,而不仅仅是父目录.还要尝试确保在对文件进行任何写入后设置此资源值,尤其是通过可能正在执行原子写入的高级API等.
所有NSFileManager和文件读/写操作都应该使用文件协调.即使在单线程的应用程序中,也会有其他进程与"您的"文件交互.进程类似于在低空间条件下运行备份或清除文件的守护程序.在您-fileExistsAtPath:和-setResourceValue:forKey:error:另一个进程之间可以更改,删除或移动您的文件及其属性.-setResourceValue:forKey:error:在没有做任何事情的情况下,实际上会返回YES并且没有错误,例如文件不存在.
标记的文件和目录NSURLIsExcludedFromBackupKey是应用程序要管理的责任.应用程序仍应在适当的时间清除这些文件或其内容,或对其增长设置限制.如果查看设备上的每个应用程序磁盘使用情况信息,您可能会猜到某些应用程序的名称无法正确执行此操作.
测试更新方案,如技术说明2285:测试iOS应用更新中所述.经常.理想情况下,iOS模拟器将具有类似于模拟内存警告的"模拟低磁盘空间"功能,但此时却没有.
如果可能的话,更改应用程序逻辑以重新创建这些文件(如果它们丢失).
| 归档时间: |
|
| 查看次数: |
3899 次 |
| 最近记录: |