У меня есть простое приложение для Mac OS X на базе NSDocument
, в котором я пытаюсь реализовать хранилище документов iCloud.Я строю с 10,7 SDK.
Я подготовил свое приложение для хранения документов iCloud и включил необходимые разрешения (AFAICT).Приложение правильно собирает, запускает и создает локальный каталог Documents для контейнера вездесущих (это заняло некоторое время, но, похоже, все работает).Я использую NSFileCoordinator
API в соответствии с рекомендациями Apple.Я вполне уверен, что я использую правильный UbiquityIdentifier
, как рекомендовано Apple (он отредактирован ниже).
Я внимательно следовал инструкциям Apple по демонстрации хранилища iCloud Document в этом видео WWDC 2011:
Сессия 107 Автосохранение и версии в Lion
Мой код выглядит практически идентично коду из этой демонстрации.
Однако, когда я вызываю мое действие для перемещения текущего документа в облако, у меня возникают проблемы с живостью при вызове метода -[NSFileManager setUbiquitous:itemAtURL:destinationURL:error:]
.Он никогда не возвращается.
Вот соответствующий код из моего NSDocument
подкласса.Он практически идентичен демонстрационному коду Apple WWDC.Поскольку это действие , оно вызывается в главном потоке (как показал демонстрационный код Apple).Тупик возникает в конце, когда вызывается метод -setUbiquitous:itemAtURL:destinationURL:error:
.Я попытался перейти к фоновому потоку, но он все равно никогда не возвращается.
Похоже, что семафор блокируется, ожидая сигнала, который никогда не приходит.
При запуске этого кода в отладчике мои исходные и целевые URL выглядят корректно, поэтому я вполне уверен, что они правильно рассчитаны, и я подтвердил, что каталоги существуют на диске.
Являюсь ли яделать что-то явно неправильное, что приведет к тому, что -setUbiquitous
никогда не вернется?
- (IBAction)moveToOrFromCloud:(id)sender {
NSURL *fileURL = [self fileURL];
if (!fileURL) return;
NSString *bundleID = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
NSString *appID = [NSString stringWithFormat:@"XXXXXXX.%@.macosx", bundleID];
BOOL makeUbiquitous = 1 == [sender tag];
NSURL *destURL = nil;
NSFileManager *mgr = [NSFileManager defaultManager];
if (makeUbiquitous) {
// get path to local ubiquity container Documents dir
NSURL *dirURL = [[mgr URLForUbiquityContainerIdentifier:appID] URLByAppendingPathComponent:@"Documents"];
if (!dirURL) {
NSLog(@"cannot find URLForUbiquityContainerIdentifier %@", appID);
return;
}
// create it if necessary
[mgr createDirectoryAtURL:dirURL withIntermediateDirectories:NO attributes:nil error:nil];
// ensure it exists
BOOL exists, isDir;
exists = [mgr fileExistsAtPath:[dirURL relativePath] isDirectory:&isDir];
if (!(exists && isDir)) {
NSLog(@"can't create local icloud dir");
return;
}
// append this doc's filename
destURL = [dirURL URLByAppendingPathComponent:[fileURL lastPathComponent]];
} else {
// get path to local Documents folder
NSArray *dirs = [mgr URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
if (![dirs count]) return;
// append this doc's filename
destURL = [[dirs objectAtIndex:0] URLByAppendingPathComponent:[fileURL lastPathComponent]];
}
NSFileCoordinator *fc = [[[NSFileCoordinator alloc] initWithFilePresenter:self] autorelease];
[fc coordinateWritingItemAtURL:fileURL options:NSFileCoordinatorWritingForMoving writingItemAtURL:destURL options:NSFileCoordinatorWritingForReplacing error:nil byAccessor:^(NSURL *fileURL, NSURL *destURL) {
NSError *err = nil;
if ([mgr setUbiquitous:makeUbiquitous itemAtURL:fileURL destinationURL:destURL error:&err]) {
[self setFileURL:destURL];
[self setFileModificationDate:nil];
[fc itemAtURL:fileURL didMoveToURL:destURL];
} else {
NSWindow *win = ... // get my window
[self presentError:err modalForWindow:win delegate:nil didPresentSelector:nil contextInfo:NULL];
}
}];
}