iCloud — иногда не удается переименовать открытые документы на другом устройстве

Проблема: я работаю над документом 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: и, кроме того, соответствующий объект может прослушивать уведомления об удалении на других устройствах.


person Obliquely    schedule 28.12.2011    source источник
comment
Около месяца я пытался заставить работать iCloud, используя только DocumentState, — именно этого мне не хватало. До добавления этого кода элементы иногда возвращались после удаления, или я получал непрерывный поток постоянно меняющихся состояний документа.   -  person Peter Johnson    schedule 16.07.2014


Ответы (1)


Этот тип URL-адреса появляется, когда UIDocument открывается локально и удаляется с удаленного устройства:

file://localhost/var/mobile/Library/Mobile%20Documents/.ubd/peer-43A0AEB6-84CE-283E-CA39-FCC4EF3BC8F8-v23/ftr/purg-

Вам нужно сначала закрыть документ, прежде чем он будет удален — обнаружьте это в accommodatePresentedItemDeletionWithCompletionHandler: NSFilePresenter.

person al_lea    schedule 13.05.2012