Может создавать, но не открывать UIManagedDocument с поддержкой iCloud.

Я создаю новый UIManagedDocument с поддержкой iCloud следующим образом:

  1. Распределить и инициализировать с URL-адресом локальной песочницы
  2. Установите параметры постоянного хранилища для поддержки iCloud: ubiquitousContentNameKey и ubiquitousContentURL. Имя, которое я генерирую уникально, и URL-адрес указывает на мой ubiquityContainer/CoreData.
  3. Сохраняйте локально в песочнице с помощью метода saveToURL UIManagedDocument.
  4. В обработчике завершения перейдите в iCloud с помощью метода setUbiquitous FileManager.

Пока этот танец работает. (Ну вроде). После того, как я вызываю setUbiquitous, я получаю сообщение об ошибке, в котором говорится, что это НЕ ПРОШЛО, однако документ перемещается в облако. Когда это будет сделано, у меня будет новый документ в облаке. Похоже, это ошибка, так как я смог воспроизвести ее с чужим кодом.

На самом деле я создаю этот документ в «Контроллере просмотра документов», в котором перечислены все документы в облаке. Поэтому, когда обработчик окончательного завершения этого нового документа завершен, он отображается в табличном представлении благодаря NSMetadataQuery. До сих пор, я думаю, довольно стандартное использование.

Чтобы отредактировать документ, пользователь нажимает и переходит к «Контроллеру просмотра документов с одним просмотром».

В этом контроллере представления мне нужно «повторно открыть» выбранный документ, чтобы пользователь мог его редактировать.

Итак, я снова прохожу ряд шагов:

  1. Выделите/инициируйте UIManagedDocument с помощью URL-адреса файла — на этот раз URL-адрес находится в облаке.
  2. Установите параметры моего постоянного хранилища, как в шаге 2 выше, с теми же настройками.

Теперь я ПОПЫТАЮСЬ выполнить шаг 3, который заключается в том, чтобы открыть документ с диска, но это не удается. Документ находится в состоянии «Закрыт | Ошибка сохранения», и попытка открытия не удалась.

Кто-нибудь знает, почему мой документ создается "ОК", перемещается в "облако" "ОК", но не открывается сразу после следующей попытки? (Действительно, попытка в рамках этого запуска приложения - см. ниже). В частности, что может привести к созданию экземпляра UIManagedDocument, но в закрытом, недоступном для открытия состоянии?

Интересно, что если я выйду из приложения и снова запущу его, я смогу нажать, перезагрузить документ и отредактировать его.

И очень редко я могу создать, затем открыть и очень кратко отредактировать, скажем, вставить один управляемый объект, а затем он переходит в это закрытие | сохранение состояния ошибки.

ИНФОРМАЦИЯ ОБ ОШИБКЕ:

Я создал подкласс UIManagedDocument и переопределил метод -handleError:, чтобы попытаться получить больше информации, и вот что я получил (вместе с некоторыми другими журналами отладки, которые я добавил):

2012-10-05 14:57:06.000 Foundations[23687:907] Загрузилось представление контроллера представления одного документа. Документ: fileURL: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/ ​​documentState: [Closed]

05.10.2012 14:57:06.052 MyApp[23687:907] Состояние документа изменено. Текущее состояние: 5 URL-адрес файла: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/ ​​documentState: [Closed | Ошибка сохранения]

05.10.2012 14:57:06.057 Foundations[23687:5303] Ошибка UIManagedDocument: имя хранилища: новый документ 34 уже используется. URL-адрес магазина: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/StoreContent.nosync/persistentStore URL-адрес используемого магазина: file:/ /localhost/var/mobile/Applications/D423F5FF-4B8E-4C3E-B908-11824D70FD34/Documents/New%20Document%2034/StoreContent.nosync/persistentStore

2012-10-05 14:57:06.059 MyApp[23687:5303] { NSLocalizedDescription = "Имя магазина: Новый документ 34 уже используется.\n\tURL-адрес хранилища: file://localhost/private/var/mobile/ Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/StoreContent.nosync/persistentStore\n\tИспользуемый URL-адрес магазина: file://localhost/var/mobile/Applications/D423F5FF-4B8E -4C3E-B908-11824D70FD34/Documents/New%20Document%2034/StoreContent.nosync/persistentStore\n"; NSPersistentStoreUbiquitousContentNameKey = "Новый документ 34"; }

Ошибка, кажется, думает, что я создаю магазин, который уже существует при последующем открытии. Должен ли я теперь установить эту опцию iCloud в постоянном магазине при втором открытии? Я пробовал этот подход, и он тоже не сработал.

Я изучил лекции Стэнфорда по UIManagedDocument и не вижу, что я делаю неправильно.

Вот мой способ создать документ и перейти в облако:

- (void) testCreatingICloudDocWithName:(NSString*)name
{

    NSURL* cloudURL = [self.docManager.iCloudURL URLByAppendingPathComponent:name isDirectory:YES];

    NSURL* fileURL = [self.docManager.localURL URLByAppendingPathComponent:name];


    self.aWriting = [[FNFoundationDocument alloc] initWithFileURL:fileURL];


    [self setPersistentStoreOptionsInDocument:self.aWriting];

    [self.aWriting saveToURL:fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
        if (success == YES) {

            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                //create file coordinator
                //move document to icloud

                NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
                NSError* coorError = nil;
                [fileCoordinator coordinateWritingItemAtURL:cloudURL options:NSFileCoordinatorWritingForReplacing error:&coorError byAccessor:^(NSURL *newURL) {

                    if (coorError) {
                        NSLog(@"Coordinating writer error: %@", coorError);
                    }

                    NSFileManager* fm = [NSFileManager defaultManager];
                    NSError* error = nil;
                    NSLog(@"Before set ubiq");
                    [fm setUbiquitous:YES itemAtURL:fileURL destinationURL:newURL error:&error];
                    if (!error) {
                        NSLog(@"Set ubiquitous successfully.");
                    }
                    else NSLog(@"Error saving to cloud. Error: %@", error);


                    NSLog(@"State of Doc after error saving to cloud: %@", self.aWriting);
                }];



            });

        }
    }];

}

Вот где я устанавливаю параметры для iCloud в persistenceStore:

- (void)setPersistentStoreOptionsInDocument:(FNDocument *)theDocument
{
    NSMutableDictionary *options = [NSMutableDictionary dictionary];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

    [options setObject:[theDocument.fileURL lastPathComponent] forKey:NSPersistentStoreUbiquitousContentNameKey];
    NSURL* coreDataLogDirectory = [self.docManager.coreDataLogsURL URLByAppendingPathComponent:[theDocument.fileURL lastPathComponent]];
    NSLog(@"Core data log dir: %@", coreDataLogDirectory);
    [options setObject:coreDataLogDirectory forKey:NSPersistentStoreUbiquitousContentURLKey];

    theDocument.persistentStoreOptions = options;
}

И вот где я пытаюсь снова открыть его:

- (void) prepareDocForUse
{

    NSURL* fileURL = self.singleDocument.fileURL;

    if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) {
        NSLog(@"File doesn't exist");
            }
    else if (self.singleDocument.documentState == UIDocumentStateClosed) {
        // exists on disk, but we need to open it
        [self.singleDocument openWithCompletionHandler:^(BOOL success) {
            if (!success) {
                NSError* error;
                [self.singleDocument handleError:error userInteractionPermitted:NO];
            }
            [self setupFetchedResultsController];
        }];
    } else if (self.singleDocument.documentState == UIDocumentStateNormal) {
        // already open and ready to use
        [self setupFetchedResultsController];
    }

}

person Jason C. Howlin    schedule 05.10.2012    source источник
comment
Это на симуляторе? Если да, то какая версия iOS? У меня и у других были очень странные проблемы с симулятором iOS 5.1 в Xcode с использованием производных кода Стэнфорда.   -  person brainray    schedule 06.10.2012
comment
Это iOS 6 на устройстве. К сожалению, вы не можете протестировать iCloud на симуляторе.   -  person Jason C. Howlin    schedule 07.10.2012
comment
Я думаю, что это метод setUbiquitous. Независимо от того, что говорят документы Apple, я думаю, что это не нужно при работе с UIManagedDocument. Если кто-то не может объяснить разницу между setUbiquitous и saveToURL, используя URL-адрес ubiquityContainer?? Кажется, все работает нормально, когда я просто сохраняю ToURL прямо в iCloud.   -  person Jason C. Howlin    schedule 07.10.2012
comment
Вы можете попробовать установить символическую точку останова на setUbiquitous. Я еще не дошел до этого момента, но кажется разумным, что фреймворк может сделать вызов.   -  person Steven McGrath    schedule 07.10.2012
comment
Привет Джейсон, у меня такая же проблема! Вы исправили это?   -  person nico9T    schedule 17.11.2013


Ответы (2)


Вы недавно тестировали различные версии iOS? Попробуйте изменить название сохраненного документа на что-то другое, кроме «Новый документ 34». У меня была такая же проблема, и я полагаю, что это было связано с конфликтующими документами, сохраненными из разных компиляций приложения SDK с использованием одного и того же URL-адреса документа.

person jwilkey    schedule 02.03.2013

Я нацелен на iOS7, я использую один UIManagedDocument в качестве базы данных моего приложения с целью лучшей интеграции CoreData и iCloud, как это предлагается Apple в своей документации. У меня была такая же проблема, я решил с помощью следующего кода.

Поскольку я написал это, я переместил настройки параметров PSC в ленивую реализацию UIManagedDocument.

Мой исходный код создал, закрыл, а затем снова открыл документ, используя стандартные функции обратного вызова с успехом. Я нашел это в книге Эрики Садун. Казалось, все в порядке, но я не мог повторно открыть только что созданный, а затем закрытый документ, потому что он находился в состоянии «ошибка сохранения». Я потерял на этом неделю, я не мог понять, что я делаю не так, потому что до повторного открытия все было идеально.

Следующий код отлично работает на моих iPhone5 и iPad3.

Никола

-(void) fetchDataWithBlock: (void (^) (void)) fetchingDataBlock
{

    //If the CoreData local file exists then open it and perform the query
    if([[NSFileManager defaultManager] fileExistsAtPath:[self.managedDocument.fileURL path]]){
        NSLog(@"The CoreData local file in the application sandbox already exists.");

        if (self.managedDocument.documentState == UIDocumentStateNormal){
            NSLog(@"The CoreData local file it's in Normal state. Fetching data.");
            fetchingDataBlock();
        }else if (self.managedDocument.documentState == UIDocumentStateClosed){
            NSLog(@"The CoreData local file it's in Closed state. I am opening it.");

            [self.managedDocument openWithCompletionHandler:^(BOOL success) {
                if(success){
                    NSLog(@"SUCCESS: The CoreData local file has been opened succesfully. Fetching data.");
                    fetchingDataBlock();
                }else{
                    NSLog(@"ERROR: Can't open the CoreData local file. Can't fetch the data.");
                    NSLog(@"%@", self.managedDocument);
                    return;
                }
            }];
        }else{
            NSLog(@"ERROR: The CoreData local file has an unexpected documentState: %@", self.managedDocument);
        }
    }else{
        NSLog(@"The CoreData local file in the application sandbox did not exist.");
             NSLog(@"Setting the UIManagedDocument PSC options.");
        [self setPersistentStoreOptionsInDocument:self.managedDocument];

        //Create the Core Data local File
        [self.managedDocument saveToURL:self.managedDocument.fileURL
                       forSaveOperation:UIDocumentSaveForCreating
                      completionHandler:^(BOOL success) {

            if(success){

                NSLog(@"SUCCESS: The CoreData local file has been created. Fetching data.");
                fetchingDataBlock();

            }else{
                NSLog(@"ERROR: Can't create the CoreData local file in the application sandbox. Can't fetch the data.");
                NSLog(@"%@", self.managedDocument);
                return;
            }

        }];

    }
}
person nico9T    schedule 19.11.2013