iOS — Как завершить длительный процесс в фоновом режиме

#ios #objective-c #cocoa-touch #facebook-graph-api

#iOS #objective-c #cocoa-touch #facebook-graph-api

Вопрос:

Мое приложение загружает видео на Facebook. Я хотел бы завершить загрузку в фоновом режиме, даже если нетерпеливый пользователь нажимает кнопку «Домой» во время загрузки.

После некоторого чтения я попробовал это:

      UIBackgroundTaskIdentifier bti = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
         [[UIApplication sharedApplication] endBackgroundTask:bti];
     }];

     [fb requestWithGraphPath:@"me/videos"
                    andParams:params
                andHttpMethod:@"POST"
                  andDelegate:self];

     [[UIApplication sharedApplication] endBackgroundTask:bti]; 
  

Работа выполняется с помощью метода запроса fb. Видео загружается на Facebook через http-соединение. Это работает нормально, но если вы запускаете приложение в фоновом режиме, нажимая кнопку «Домой» во время загрузки, загрузка приостанавливается. Если вы переместите приложение на передний план, загрузка возобновится.

Я надеялся, что произойдет то, что загрузка завершится в фоновом режиме.

Есть надежда заставить это работать? Я делаю что-то не так со всей этой задачей beginBackgroundTask? Это кажется слишком простым для такой работы, но, похоже, так говорят документы.

Любая помощь, очень ценится.

— Джон

Комментарии:

1. @jhon мне нужно загружать видео в фоновом режиме. могу ли я подать в суд на этот блок кода?? есть ли вероятность, что Apple может отклонить мое приложение, поскольку выполнение длительного процесса в фоновом режиме имеет ограничения

Ответ №1:

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

Мой приведенный выше код выполняет код ‘end’ слишком рано, что приводит к почти немедленному завершению фонового выполнения.

Способ сделать это — сделать что-то вроде:

    // make sure save can complete in the background
    if ([[UIDevice currentDevice] isMultitaskingSupported])
        backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{}];
  

когда начинается длительная задача. Как указано выше в hypercrypt, ‘backgroundTaskID должен быть ivar или чем-то, что вы можете получить позже, когда завершится длительная задача.

Когда задача завершится, выполните что-то вроде:

 if ([[UIDevice currentDevice] isMultitaskingSupported]) {
    [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
    backgroundTaskID = UIBackgroundTaskInvalid;
}
  

Это работает как шарм.

Комментарии:

1. Джон — Вы отделяете поток и помещаете все это в поток, или вы ждете сигнала от нового потока, а затем вызываете endBackgroundTask в основном потоке?

2. @Chris Я думаю, было бы неплохо перевести процесс в новый поток. Если вам приходится делать это в фоновом режиме, это, вероятно, долгая и сложная задача, которую следует выполнять в другом потоке, чтобы избежать засорения пользовательского интерфейса.

Ответ №2:

Вам нужно вызвать обратный вызов [[UIApplication sharedApplication] endBackgroundTask:bti]; делегата. Вам нужно будет сохранить bti в ivar или как статическую переменную.

Комментарии:

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