Как я могу определить, что iCloud завершил загрузку документа, а также запустить обработчик завершения? - PullRequest
1 голос
/ 30 декабря 2011

При загрузке документа из iCloud необходимо позвонить на

openWithCompletionHandler:^(BOOL success)completionHandler

Эта функция запускает фоновый поток, который загружает файл из iCloud, и после завершения загрузки запускает обработчик завершения.

Пока это происходит, любой код после этого вызова продолжает выполняться.

Как я могу остановить продолжение работы программы до завершения загрузки?

Сразу после вызова для загрузки из облака мой код пытается использовать документ - но, конечно, поскольку загрузка не завершена, код вылетает.

Подробности следуют:

В настоящее время я работаю над библиотекой сохранения файлов, которая обеспечивает сохранение / загрузку файлов, шифрование, сжатие и поддержку iCloud. Пользователи делают вызов моей библиотечной функции LoadFileAtPath, и есть параметр, указывающий, хотят ли я, чтобы я проверял iCloud для этого конкретного файла.

Когда функция запускается, и я собираюсь проверить iCloud, первое, что я делаю, это вызываю функцию iCloudload, например:

bool cloudLoad = [iCloudStorageManager readFileFromiCloud:filePath name:fileName];

внутри этой функции я вызываю openWithCompletionHandler, вот так:

if ([fileManager fileExistsAtPath:[docURL path]]) 
        {
            [doc openWithCompletionHandler:^(BOOL success){
                if (!success) 
                {
                    // Handle the error.
                    NSLog(@"Failed to retrieve document:%@ from iCloud URL:%@.", fileName, [docURL absoluteString]);
                }
                else
                {
                    NSLog(@"Replacing document in sandbox with iCloud version");
                    BOOL* dir = nil;
                    if (![fileManager fileExistsAtPath:filePath  isDirectory:dir])
                    {
                        NSError *fileError = nil;
                        if(![fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:&fileError])
                        {
                            NSLog(@"Error creating file directory: %@\n%@\n%@\n%@", [fileError localizedDescription], [fileError localizedFailureReason], [fileError localizedRecoveryOptions], [fileError localizedRecoverySuggestion]);
                        }

                    }
                    // save new data if success
                    [iCloudStorage replaceDocumentInSandboxWith:doc newData:doc.loadedContents];
                }
            }];
            [doc release];
        }

После этого мой код продолжает пытаться получить данные и выполнять с ними различные действия, такие как расшифровка, распаковка и передача данных файла вызывающей стороне.

Мое текущее (хакерское) решение состояло в том, чтобы после первоначального вызова readFileFromiCloud иметь цикл, который проверяет bool, вот так:

while (!cloudDidFinishLoad) 
{
     sleep(10);
}

Этот bool инициализируется как false, и в функции, показанной выше "replaceDocumentInSandboxWith", bool установлен в true.

Однако я обнаружил, что это приводит к зависанию программы, она никогда не завершает загрузку файла iCloud и никогда не вызывается обработчик завершения.

Я не знаю, что мне делать. Мне нужна программа, чтобы остановить выполнение кода до завершения загрузки, но я не знаю, как это сделать.

Ответы [ 2 ]

1 голос
/ 12 апреля 2012

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

Тогда в вашем главном контроллере можно установить делегат, и как только файл будет готов, вы сможете получить вызов из библиотеки, которую файл готов использовать. Так что псевдокод будет примерно таким ...

  1. Создать iCloudStorageManager
  2. Установить себя в качестве делегата iCloudStorageManager
  3. вызов файла, открытого в iCloudStorageManager
  4. Делайте все, что вам нужно здесь, установите индикатор активности или заблокируйте интерфейс, или ни того, ни другого, и просто предполагайте, что это работает, если только делегат не скажет, что это не так. По сути, здесь ваш блок завершится, и когда вызывается функция делегата, ваш главный контроллер восстановит управление интерфейсом.

  5. В функции делегата вы получите от iCloudStorageManager статус того, был ли он успешным или нет. Получив этот вызов от iCloudStorageManager, вы можете освободить интерфейс, опубликовать уведомление о том, что все прошло хорошо или что дела пошли на юг, и предложить ответ ... все, что вы хотите сделать.

Но я бы так с этим справился. (Да, это старый вопрос, но я чувствовал, что у меня есть некоторое понимание:))

0 голосов
/ 30 декабря 2011

Замораживание пользовательского интерфейса (через этот спящий вызов в главном потоке) во время ожидания завершения загрузки файла мне кажется очень жестким, и я ожидаю, что вашим клиентам это не понравится.

Почему бы не выбросить счетчик активности, например:

A nice

А затем убрать его, когда вызывается ваш обработчик завершения iCloud?Пока представление активности находится на экране, вы можете отключить оставшуюся часть взаимодействия с пользовательским интерфейсом с помощью свойства userInteractionEnabled UIView (при значении FALSE).

...