End*_*ker 2 iphone nsfilemanager ios ios6
我无法让NSFileManager方法replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:在iOS 6中工作.调用此方法并在iOS 5上正常工作的应用程序在iOS 6上存在重大问题.运行iOS 6.0以下版本的设备上不会出现此问题.如果应用程序是由Xcode在iOS模拟器中启动的,则不会出现此问题.否则问题似乎是普遍存在的.
这是我试图执行的测试代码:
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *destinationPath = [documentsDirectory stringByAppendingPathComponent:@"test.txt"];
NSString *sourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"test.txt"];
// Create initial file in documents directory
if (![fileManager fileExistsAtPath:destinationPath])
{
BOOL fileCopied = [fileManager copyItemAtPath:sourcePath
toPath:destinationPath
error:&error];
if (!fileCopied)
[[self statusLabel] setText:[NSString stringWithFormat:@"Creation Error:\n\n%@",
[error localizedDescription]]];
}
// Replace file in documents directory with copy of file from app bundle
if ([fileManager fileExistsAtPath:destinationPath])
{
NSURL *destinationURL = [NSURL fileURLWithPath:destinationPath];
BOOL fileReplaced = [fileManager replaceItemAtURL:destinationURL
withItemAtURL:[NSURL fileURLWithPath:sourcePath]
backupItemName:nil
options:0
resultingItemURL:&destinationURL
error:&error];
if (!fileReplaced)
[[self statusLabel] setText:[NSString stringWithFormat:@"Replacement Error:\n\n%@",
[error localizedDescription]]];
else
[[self statusLabel] setText:@"Successfully replaced file."];
}
Run Code Online (Sandbox Code Playgroud)
它在文档目录中创建文件(如果该文件尚不存在).然后,它尝试使用应用程序包中的文件副本替换文档目录中的文件.然后它报告文件创建/替换的状态.正如我之前所说的,如果它在iOS 5或更低版本上运行,或者如果它在iOS模拟器中运行并且Xcode附加到该进程,它将被替换为罚款.但是,如果它在没有Xcode的iOS 6设备或iOS模拟器上运行,则替换失败并返回错误.本地化的错误描述是The operation couldn’t be completed. (Cocoa error 512.).
错误的用户信息字典是:
{
NSFileNewItemLocationKey = "file://localhost/var/mobile/Applications/487FBB9E-A2BD-4CF2-BB38-F36764623C2F/Test.app/test.txt";
NSFileOriginalItemLocationKey = "file://localhost/var/mobile/Applications/487FBB9E-A2BD-4CF2-BB38-F36764623C2F/Documents/test.txt";
NSURL = "file://localhost/var/mobile/Applications/487FBB9E-A2BD-4CF2-BB38-F36764623C2F/Documents/test.txt";
NSUnderlyingError = "Error Domain=NSCocoaErrorDomain Code=513 \"The operation couldn\U2019t be completed. (Cocoa error 513.)\" UserInfo=0x1d58d350 {NSFilePath=/var/mobile/Applications/487FBB9E-A2BD-4CF2-BB38-F36764623C2F/Test.app/test.txt, NSURLUnsetValueKeysKey=<CFArray 0x1d58d180 [0x39b9d100]>{type = immutable, count = 2, values = (\n\t0 : <CFString 0x39b945b4 [0x39b9d100]>{contents = \"NSURLFileSecurityKey\"}\n\t1 : <CFString 0x39b943d4 [0x39b9d100]>{contents = \"NSURLCreationDateKey\"}\n)}, NSUnderlyingError=0x1d58d010 \"The operation couldn\U2019t be completed. Operation not permitted\", NSURL=file://localhost/var/mobile/Applications/487FBB9E-A2BD-4CF2-BB38-F36764623C2F/Test.app/test.txt}";
}
Run Code Online (Sandbox Code Playgroud)
我在App Store上有一个应用程序,它取决于这种方法.实时应用程序在iOS 5上继续工作没有缺陷,但在iOS 6上由于方法失败而存在巨大问题.有谁知道为什么这种方法失败了?
NSFileManager方法replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:不是复制方法; 这是一种移动方法.即,文件不会替换为替换文件的副本,而是替换文件本身.由于应用程序不应该能够修改自己的bundle,因此上述代码在任何版本的iOS中都不应该有效.
为了保持原子性,解决方案是首先将替换文件的副本保存到临时目录,然后将文件替换为临时目录中的副本.
这是固定的测试代码:
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"txt"];
NSString *destinationPath = [documentsDirectory stringByAppendingPathComponent:@"test.txt"];
// Create initial file in documents directory
if (![fileManager fileExistsAtPath:destinationPath])
{
BOOL fileCopied = [fileManager copyItemAtPath:sourcePath
toPath:destinationPath
error:&error];
if (!fileCopied)
[[self statusLabel] setText:[NSString stringWithFormat:@"Creation Error:\n\n%@", [error localizedDescription]]];
}
// Replace file in documents directory with copy of file from app bundle
if ([fileManager fileExistsAtPath:destinationPath])
{
// Create temporary file
NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"test.txt"];
BOOL tempCopied = [fileManager copyItemAtPath:sourcePath
toPath:tempPath
error:&error];
if (!tempCopied)
[[self statusLabel] setText:[NSString stringWithFormat:@"Temp Creation Error:\n\n%@", [error localizedDescription]]];
// Replace file with temporary file
NSURL *destinationURL = [NSURL fileURLWithPath:destinationPath];
BOOL fileReplaced = [fileManager replaceItemAtURL:destinationURL
withItemAtURL:[NSURL fileURLWithPath:tempPath]
backupItemName:nil
options:0
resultingItemURL:&destinationURL
error:&error];
if (!fileReplaced)
[[self statusLabel] setText:[NSString stringWithFormat:@"Replacement Error:\n\n%@", [error localizedDescription]]];
else
[[self statusLabel] setText:@"Successfully replaced file."];
}
Run Code Online (Sandbox Code Playgroud)