Я реализую запускаемый вручную процесс миграции для приложения на основе 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, чтобы убедиться, что материалы CoreData не имеют к этому никакого отношения.
Затем я заметил в официальный документации, что newitemURL
должен находиться в каталоге, который считается подходящим для временных файлов. Я предположил, что это означает каталог, возвращенный URLForDirectory:inDomain:appropriateForURL:create:error:
с использованием NSItemReplacementDirectory
в качестве пути поиска.
Это тоже не сработало! В итоге я вернулся к реализации логики замены с использованием отдельных операций, но это не атомарно, небезопасно и все такое плохое.
Есть ли у кого-нибудь работающий фрагмент кода, работающий на iOS, который либо возвращает YES при вызове replaceItemAtURL
, либо фактически помещает информацию об ошибке в указатель ошибки?
Любая помощь высоко ценится.
РЕДАКТИРОВАТЬ. Тестовый код приведен ниже. Это выполняется в 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
NSTemporaryDirectory()
, так иNSCachesDirectory
, и он все еще терпит неудачу без каких-либо ошибок. Вам повезло? - person Tony   schedule 08.04.2011resultingItemURL
может быть нулевым, поэтому я изменил код, включив ненулевые значения как для него, так и дляbackupItemName
, и все равно получаю тот же результат. Возвращаемое значение из вызова замены — НЕТ, но ошибка по-прежнему равна нулю. В основном все еще кажется сломанным! Тем не менее спасибо за предложение. - person glenc   schedule 11.04.2011replaceItemAtURL
... - person glenc   schedule 12.05.2011tmpDir
равно нулю после вызоваURLForDirectory:etc:
, и в результатеu2
также равно нулю, а вызовreplaceItemAtURL:etc:
приводит к сбою приложения. Что вы на самом деле делаете? Этот код не тот. - person Tom Harrington   schedule 23.06.2011rename()
? - person tc.   schedule 09.03.2013