replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:在iOS 6中损坏了吗? [英] replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error: broken in iOS 6?

查看:72
本文介绍了replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:在iOS 6中损坏了吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法使NSFileManager方法replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:在iOS 6中工作.在iOS 6上,调用此方法且在iOS 5上运行良好的应用程序存在重大问题.在运行iOS 6.0以下版本的设备上不会发生此问题.如果通过Xcode在iOS模拟器中启动了该应用程序,则不会发生此问题.否则问题似乎很普遍.

I cannot get the NSFileManager method replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error: to work in iOS 6. Apps that call this method and worked fine on iOS 5 have major issues on iOS 6. The problem does not occur on devices running versions of iOS below 6.0. The problem does not occur if the app is launched in the iOS Simulator by Xcode. Otherwise the problem seems to be universal.

这是我要执行的测试代码:

Here is the test code I am trying to execute:

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."];
}

如果尚不存在,它将在documents目录中创建文件.然后,它尝试使用来自应用程序捆绑包的文件副本替换documents目录中的文件.然后,它报告文件创建/替换的状态.如我之前所说,如果它是在iOS 5或更低版本上运行的,或者是在附加了Xcode的iOS模拟器中运行的,则可以很好地替换它.但是,如果它在没有Xcode的iOS 6设备或iOS模拟器上运行,则替换失败,并返回错误.本地化的错误描述是The operation couldn’t be completed. (Cocoa error 512.).

It creates the file in the documents directory, if it doesn’t already exist. It then attempts to replace the file in the documents directory with a copy of a file from the app bundle. It then reports the status of the file creation/replacement. As I said before, it replaces fine if it’s being run on iOS 5 or lower or if it’s being run in the iOS Simulator with Xcode attached to the process. However, if it’s run on an iOS 6 device or the iOS Simulator without Xcode the replacement fails and an error is returned. The localized error description is The operation couldn’t be completed. (Cocoa error 512.).

该错误的用户信息字典是:

The user info dictionary for the error is:

{
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}";
}

我在App Store上有一个依赖于此方法的应用程序.实时应用程序可以在iOS 5上正常运行,但在iOS 6上由于方法失败而存在巨大问题.有谁知道为什么这种方法失败了?

I have an app on the App Store which depends on this method. The live app continues to work without flaw on iOS 5, but on iOS 6 it is has huge problems due to the method failure. Does anyone know why this method is failing?

推荐答案

NSFileManager方法replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:不是复制方法.这是一种移动方法.也就是说,该文件不会被替换文件的副本替换,而是被替换文件本身替换.由于应用程序不应该能够修改其自己的捆绑软件,因此以上代码在任何版本的iOS上均不起作用.

The NSFileManager method replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error: is not a copy method; it is a move method. I.e., the file isn’t replaced with a copy of the replacement file, but with the replacement file itself. Since an app is not supposed to be able to modify its own bundle, the above code should never have worked in any version of iOS.

要保持原子性,解决方案是先将替换文件的副本保存到临时目录中,然后将文件替换为临时目录中的副本.

To retain atomicity, the solution is to first save a copy of the replacement file to the temporary directory, then replace the file with the copy in the temporary directory.

这是固定的测试代码:

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."];
}

这篇关于replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:在iOS 6中损坏了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆