Вы не очень хорошо понимаете модель потоков, и вы, вероятно, собираетесь выстрелить себе в ногу, если начнете добавлять асинхронный код, не понимая, что происходит.
Код, который вы написали, выполняется восновная ветка приложения.Но когда вы думаете об этом, вам не нужно писать никакой функции main
- вы просто реализуете делегат приложения и обратные вызовы событий (например, сенсорные обработчики), и они каким-то образом запускаются автоматически, когда приходит время.Это не волшебство, это просто объект Какао, называемый Run Loop .
Run Loop - это объект, который получает все события, обрабатывает таймеры (как в NSTimer
) и запускаетваш код.Это означает, что когда вы, например, что-то делаете, когда пользователь нажимает кнопку, дерево вызовов выглядит примерно так:
main thread running
main run loop
// fire timers
// receive events — aha, here we have an event, let’s call the handler
view::touchesBegan…
// use tapped some button, let’s fire the callback
someButton::touchUpInside
yourCode
Теперь yourCode
делает то, что вы хотите, и Run Loopпродолжает работать.Но когда вашему коду требуется слишком много времени для завершения, как, например, в вашем случае, цикл выполнения должен ждать, и поэтому события не будут обработаны, пока ваш код не завершится.Это то, что вы видите в своем приложении.
Чтобы разрешить ситуацию, вы должны запустить длинную операцию в другом потоке.Это не очень сложно, но вам все же придется подумать о нескольких потенциальных проблемах.Запуск в другом потоке может быть так же просто, как вызов performSelectorInBackground
:
[appDelegate performSelectorInBackground:@selector(GetApps) withObject:nil];
И теперь вам нужно придумать способ сообщить приложению, что данные загружены, например:используя уведомление или вызывая селектор в главном потоке.Кстати, хранение данных в делегате приложения (или даже использование делегата приложения для загрузки данных) не очень элегантное решение, но это уже другая история.
Если вы выберете решение performSelectorInBackground
,взгляните на связанный вопрос о управлении памятью во вторичных потоках .Вам потребуется собственный пул автоматического выпуска, чтобы не допускать утечки автоматически выпущенных объектов.
Обновление ответа через некоторое время - в настоящее время обычно лучше всего запускать код в фоновом режиме с помощью Grand Central Dispatch:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// No explicit autorelease pool needed here.
// The code runs in background, not strangling
// the main run loop.
[self doSomeLongOperation];
dispatch_sync(dispatch_get_main_queue(), ^{
// This will be called on the main thread, so that
// you can update the UI, for example.
[self longOperationDone];
});
});