2011-12-28 5 views
2

Я новичок в разработке iPhone и работаю над приложением последние несколько месяцев, и время, когда время позволяет работать. В частности, я написал функцию обновления для обновления базы данных sqlite на телефоне с данными из нашей онлайн-базы данных mysql. Само обновление работало нормально, но оно заморозило пользовательский интерфейс до тех пор, пока обновление не будет завершено.Правильный способ выполнения многопоточности

Это действительно не было слишком большой сделкой, но даже при том, что приложение телефона сообщило, что оно обновляется (кнопка оставила синий цвет нажатия и текст на нем изменился на «Обновление», а также текстовое сообщение над ним, показывающее, что оно обновляется), некоторые люди все еще не знали, что это обновление ... Итак, я тогда захотел поместить обновление в свой собственный поток, чтобы я мог показать, что небольшое изображение обработки в середине экран также (потому что изображение замерло, когда я вставлял его без многопоточности).

Моя проблема: я не знаю, как правильно начать поток при «приостановке» приложения (не позволяя пользователю перейти на другие страницы и т. Д.), А затем «приостанавливая» приложение после его завершения.

У меня есть эта работа, но только в симуляторе. Он не работает после того, как мы загрузим его в iTunes и загрузим после того, как он его одобрит. Приложение навсегда приостановлено. Вот мой текущий код:

Основной поток, который запускает процесс обновления:

- (IBAction)update:(id)sender{ 
    [NSThread detachNewThreadSelector:@selector(doUpdate:) toTarget:[UpdateViewController class] withObject:nil]; 

    canGo = FALSE; 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(threadDone:) name:NSThreadWillExitNotification object:nil]; 

    while (!canGo){ 
    } 

    [activity stopAnimating]; 
    activity.hidden = YES; 
    status_text.text = @"Update Successful! You may have to close and restart the app."; 
} 

Как вы можете видеть здесь, я создать еще один поток, то есть в то время цикла до бесконечности держать все другие процессы, от происходящих поэтому пользователь не может перемещаться внутри программы. (Я знаю, что это ДОЛЖНО быть неправильным, но я не могу найти пример правильного способа сделать это.) Перед тем, как вызывать эту функцию, я запускаю анимацию для изображения обработки. (И да, я знаю, что это не технически «функции» из того, что я читал, но, пожалуйста, извините неправильную терминологию. Как я уже сказал, я новичок.)

Затем в новой ветке :

+ (void)doUpdate:(id)param{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; 

    // Stuff happens here 

    UpdateViewController *talkThread = [[UpdateViewController alloc] init]; 
    [talkThread threadDone:nil]; 

    [pool drain]; 
} 

И еще одна функция вызывается обоими (который работает на тренажере, но не после того, как ITunes скачать):

-(void)threadDone:(NSNotification*)arg { 
    NSLog(@"Exiting"); 
    canGo = TRUE; 
} 

Я также попытался закомментировать код, который вызывает «threadDone» и в моей новой резьбе я использовал:

[self performSelectorOnMainThread:@selector(finishLoop) withObject:nil waitUntilDone:FALSE]; 

с новой функцией, которая сделала точно такую ​​же вещь, как threadDone:

-(void)finishLoop{ 
    NSLog(@"Finish Loop"); 
    canGo = TRUE; 
} 

Это ничего не делать вообще. В отладчике finalLoop никогда не вызывался вообще, когда я прошел через обновление. Но я не получаю ошибок в строке «performSelectorOnMainThread», поэтому я не понимаю, что с этим не так.

Поэтому я был бы очень признателен за то, что кто-то объяснил правильный способ настройки другого потока, который приостанавливает пользовательский интерфейс без его замораживания (чтобы я мог отображать текст, например, «гостиницы были обновлены» или что-то, место, и поэтому изображение прогресса не замерзает), а затем приостанавливает пользовательский интерфейс после завершения обновления. Спасибо вам большое заблаговременно, так как это уже давно стало болью.

ответ

2

Чтобы пользователь не взаимодействовал с пользовательским интерфейсом, звоните [[UIApplication sharedApplication] beginIgnoringInteractionEvents]. Когда пользователю разрешено снова взаимодействовать, вызовите endIgnoring....

EDIT: Вы спросили, как назвать что-то, когда нить заканчивается. Вот как выглядит архитектура потоков GCD:

dispatch_async(my_queue, ^{ 
    // ... do stuff in a background thread ... 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // ... the thread is over, do stuff on the main thread ... 
    }); 
}); 

Это действительно так просто.

+0

Звучит неплохо, но я не знаю, как правильно называть что-то, когда заканчивается нить. Кажется, он работает на симуляторе, но не после загрузки из iTunes. – James

+0

Ну, первый шаг не использует все, что 'detachNewThreadSelector:' материал. Подобные ситуации - это то, почему мы благословлены Великой Центральной диспетчерской. Это позволяет очень легко вызвать что-то на основной поток, когда поток заканчивается. – matt

+0

Ну, я не знал, как настроить переменную «myqueue», но я установил ее как 'dispatch_queue_t my_queue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);'. Я не получаю ошибок при входе в первую очередь, но 'dispatch_async (dispatch_get_main_queue(),^{' никогда не вводится. Он не выполняет код между этим. – James

1

Чтобы предотвратить перемещение пользователя во время работы в фоновом режиме, вы должны либо установить свойство enabled на каждом UIControl (UIButton, UITextField и т. Д.), Либо, возможно, наложить прозрачный UIView на весь пользовательский интерфейс, чтобы блокировать касания. Бесконечные петли никогда не будут правильным ответом. Эффект их использования победит цель использования фонового потока. Если есть определенные действия пользователя, вы не знаете, как заблокировать во время обновления, опубликуйте в комментариях, и мы сможем понять это.

+0

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

1

Вы можете использовать MBProgressHUD и сэкономить вам некоторую работу. Эта вещь будет соответствовать вашим потребностям. Отображение индикатора процесса при выполнении некоторой работы в фоновом режиме.

+0

Но действительно ли нужно включить полный класс, чтобы перевернуть флаг в коде? Мне не нужны никакие дополнительные уведомления, просто хочу знать, когда поток выходит. – James

1

Вы посмотрели фреймворк MBProgressHUD? Это с открытым исходным кодом и, похоже, соответствует тому, что вы ищете.

MBProgressHUD - это класс внедрения iPhone, который отображает полупрозрачную HUD с индикатором прогресса и некоторыми дополнительными ярлыками, когда работа выполняется в фоновом потоке. HUD означает замену незарегистрированного частного UIKit UIProgressHUD с некоторыми дополнительными функциями.

Смежные вопросы