Проблема: я работаю над документом iCloud на устройстве A, например. Ipod Touch. Затем я меняю имя документа на устройстве B, например. мой Mac (через Finder). Изменение попадает в облако, и после паузы устройство А узнает об этом.
А потом:
- иногда все в порядке — я получаю изменение имени через измененное свойство
fileURL
и могу соответствующим образом обновить свой интерфейс — документ продолжает вести себя так, как должен - иногда URL-адрес файла документа возвращается как нечто вроде:
file://localhost/var/mobile/Library/Mobile%20Documents/.ubd/peer-43A0AEB6-84CE-283E-CA39-FCC4EF3BC8F8-v23/ftr/purg-012fdcfbe3b3bbce6e603fdfd2f000b2cb28649e95
Неудивительно, что этот файл не сохраняется.
Может ли кто-нибудь объяснить, что происходит и как это обойти?
Фон
NSMetadataQuery
прекрасно воспринял изменение имени. Так, например, я могу переименовывать документы, которые не открыты, и все мои функции iCloud работают нормально. Проблема возникает только с открытыми документами.Другие функции iCloud работают нормально, например. Я могу изменить контент на одном устройстве, например. мой Mac и обнаружить, а затем обновить мой интерфейс на другом устройстве, например. мой iPod Touch, на котором открыт соответствующий документ iCloud.
Впервые я заметил это, когда добавил переопределение для
presentedItemDidMoveToURL:
в свой подкласс UIDocument. Переопределение надежно улавливает изменения имени, сделанные в облаке, например. переименование документа на другом устройстве. Затем иногда newURL является конечным ожидаемым URL-адресом для переименованного документа, то есть чем-то разумным, из которого я могу извлечь новое имя, используя `lastPathComponent', обновить свой интерфейс и т. д. В других случаях newURL является документом в каком-то другой каталог с последним компонентом пути, начинающимся с «pug-», например чистка-012fdcfbe3b3bbce6e603fdfd2f000b2cb28649e95.- (void) presentedItemDidMoveToURL:(NSURL *) newURL; { [super presentedItemDidMoveToURL: newURL]; if ([(id)[self delegate] respondsToSelector:@selector(documentNameChanged:)]) { [[self delegate] documentNameChanged: self]; } }
Метод
presentedItemDidMoveToURL:
не является основной причиной проблемы. Например, если я вообще не переопределяю этот метод, а периодически проверяю viewController, который следит за открытым документом, то иногда после переименованияfileURL
вернет новое имя и иногда возвращается `purge-.....'. Таким образом, проблема, похоже, связана с тем, как обрабатывается переименование.
Обновить
Как указал al_lea, проблема здесь была связана с accommodatePresentedItemDeletionWithCompletionHandler:
. Расширяя ответ al_lea, я добавил приведенный ниже код в свой подкласс UIDocument. Это решило проблему.
- (void) accommodatePresentedItemDeletionWithCompletionHandler: (void (^) (NSError *errorOrNil)) completionHandler
{
PresentedDocument* presentedDocument = [self retain];
[presentedDocument closeWithCompletionHandler: ^(BOOL success) {
NSError* error = nil;
if (!success)
{
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
@"Could not close document that is being deleted on another device",
NSLocalizedDescriptionKey, nil];
error = [NSError errorWithDomain: @"some_suitable_domain"
code: 101
userInfo: userInfo];
}
completionHandler(error); // run the passed in completion handler (required)
dispatch_async(dispatch_get_main_queue(), ^
{
[[NSNotificationCenter defaultCenter] postNotificationName: NOTIFY_presentedDocumentDeletedOnAnotherDevice
object: presentedDocument
userInfo: nil];
[presentedDocument tidyUpAfterDelete]; // app specific tidy up
[presentedDocument release];
});
}];
}
С этим кодом нет ложных и запутывающих вызовов PresentItemDidMoveToURL: и, кроме того, соответствующий объект может прослушивать уведомления об удалении на других устройствах.