在 iOS 上,replaceItemAtURL 失败且没有错误,但在 OSX 上工作正常
我正在为基于 CoreData 的应用程序实现手动触发的迁移过程,迁移成功完成后,我尝试使用 replaceItemAtURL:withItemAtURL:backupItemName 将迁移的数据库移回到原始数据库的顶部:options:resultingItemURL:error:
。
问题是,在 iOS 上,我所做的任何事情都不会让这个方法返回 YES,但是它也不会将任何内容放入错误指针中以让您查看出了什么问题。
我在其他地方读过一些东西(例如 http://www.cocoabuilder.com/archive/cocoa/287790-nsdoc-magic-file-watcher-ruins-core-data-migration.html) 表示不关闭所有 CoreData 对象(例如 NSMigrationManager、NSManagedObjectModel 等)在尝试替换之前可能是原因,但事实并非如此。我什至实现了一些完全不涉及 CoreData DB 的两个文件创建和交换的东西,以验证 CoreData 的东西与它没有任何关系。
然后我注意到 官方文档表明 newitemURL
应该位于适合临时文件的目录中。我假设这意味着 URLForDirectory:inDomain:propertyForURL:create:error:
使用 NSItemReplacementDirectory
作为搜索路径返回的目录。
那也没用!我最终又转而使用单独的操作来实现替换逻辑,但这是非原子的、不安全的以及所有这些不好的东西。
是否有人拥有在 iOS 上运行的工作代码片段,该代码片段要么从调用 replaceItemAtURL
返回 YES,要么实际上将错误信息放入错误指针中?
非常感谢任何帮助。
编辑 - 下面包含测试代码。它在主线程上的 application:didFinishLaunchingWithOptions:
中运行。
NSFileManager *fm = [[NSFileManager alloc] init];
NSError *err = nil;
NSURL *docDir = [NSURL fileURLWithPath:[self applicationDocumentsDirectory]];
NSURL *tmpDir = [fm URLForDirectory:NSItemReplacementDirectory
inDomain:NSUserDomainMask
appropriateForURL:docDir
create:NO
error:&err];
NSURL *u1 = [docDir URLByAppendingPathComponent:@"f1"];
NSURL *u2 = [tmpDir URLByAppendingPathComponent:@"f2"];
NSURL *repl = nil;
[fm createFileAtPath:[u1 path]
contents:[[NSString stringWithString:@"Hello"]
dataUsingEncoding:NSUTF8StringEncoding]
attributes:nil];
[fm createFileAtPath:[u2 path]
contents:[[NSString stringWithString:@"World"]
dataUsingEncoding:NSUTF8StringEncoding]
attributes:nil];
BOOL test = [fm replaceItemAtURL:u1 withItemAtURL:u2 backupItemName:@"f1backup"
options:0 resultingItemURL:&repl error:&err];
// At this point GDB shows test to be NO but error is still nil
I'm implementing a manually-triggered migration process for a CoreData-based app, and after the migration completes successfully, I'm trying to move the migrated DB back over the top of the original one using replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:
.
The problem is that on iOS, nothing I do will make this method return YES, however it also never puts anything into the error pointer to allow you to see what's going wrong.
I'd read things elsewhere (e.g. http://www.cocoabuilder.com/archive/cocoa/287790-nsdoc-magic-file-watcher-ruins-core-data-migration.html) indicating that not shutting down all the CoreData objects (e.g. NSMigrationManager, NSManagedObjectModel etc) before attempting the replace might be the cause, but that wasn't it. I even implemented a little two file create-and-swap thing that didn't involve CoreData DBs at all to verify that the CoreData stuff didn't have anything to do with it.
I then noticed in the official documentation that the newitemURL
is supposed to be in a directory deemed appropriate for temporary files. I assumed that that meant a directory returned by URLForDirectory:inDomain:appropriateForURL:create:error:
using NSItemReplacementDirectory
as the search path.
That didn't work either! I ended up falling back to implementing the replacement logic using separate operations, but this is non-atomic and unsafe and all that bad stuff.
Does anyone have a working snippet of code that runs on iOS that either return YES from a call to replaceItemAtURL
or actually puts error information into the error pointer?
Any help much appreciated.
EDIT - Test code included below. This runs in application:didFinishLaunchingWithOptions:
on the main thread.
NSFileManager *fm = [[NSFileManager alloc] init];
NSError *err = nil;
NSURL *docDir = [NSURL fileURLWithPath:[self applicationDocumentsDirectory]];
NSURL *tmpDir = [fm URLForDirectory:NSItemReplacementDirectory
inDomain:NSUserDomainMask
appropriateForURL:docDir
create:NO
error:&err];
NSURL *u1 = [docDir URLByAppendingPathComponent:@"f1"];
NSURL *u2 = [tmpDir URLByAppendingPathComponent:@"f2"];
NSURL *repl = nil;
[fm createFileAtPath:[u1 path]
contents:[[NSString stringWithString:@"Hello"]
dataUsingEncoding:NSUTF8StringEncoding]
attributes:nil];
[fm createFileAtPath:[u2 path]
contents:[[NSString stringWithString:@"World"]
dataUsingEncoding:NSUTF8StringEncoding]
attributes:nil];
BOOL test = [fm replaceItemAtURL:u1 withItemAtURL:u2 backupItemName:@"f1backup"
options:0 resultingItemURL:&repl error:&err];
// At this point GDB shows test to be NO but error is still nil
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我在 iOS 上使用 URL 的所有
NSFileManager
方法都遇到了问题。但是,所有使用 Path 的方法都有效。因此,我认为您应该使用removeItemAtPath:error:
和copyItemAtPath:toURL:error:
来实现此目的。希望有帮助
I have experienced issues with all the
NSFileManager
methods using an URL on iOS. However, all the methods using Path work. So I think you should useremoveItemAtPath:error:
andcopyItemAtPath:toURL:error:
for that purpose.Hope it helps
在mac文件系统中不区分大小写,但在IOS中则如此。即使一个位置不能有两个名称相同但大小写不同的文件,路径也是区分大小写的。因此,如果文件具有 .JPEG 并且在您的代码中传递带有 .jpeg 的链接,它将失败。
您的情况可能并非如此,但只是分享什么,
尽管奇怪的是它应该给您错误。
In mac file system is not case sensitive, but in IOS it. Even though you cant have two files with same name but with different case at one location, the path is case sensitive. So if file is has .JPEG and in your code you are passing link with .jpeg it will fail.
It may not be the case with you but just what to share
Although strangely it should give you error.