вызов dispatch_async в applicationDidFinishLaunchWithOptions не ведет себя так, как я ожидал - PullRequest
0 голосов
/ 20 октября 2011

Я совершенно новичок в потоках в iOS. У меня есть приложение на основе панели вкладок с вкладками следующим образом:

  • Главный экран с кнопками, функции которых предназначены только для изменения selectedSegmentIndex
  • Экран листинга информации, в котором используется здоровенный вызов веб-службы в методе init [self doLoadData]
  • Два других экрана, которые не имеют значения для этой цели

Я хочу пойти дальше и вызвать этот метод init, прежде чем я на самом деле вызову tabBarController.selectedSegmentIndex = 1. Итак, я сделал это в моем applicationDidFinishLaunching:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [Constants configureApp];</p> <pre><code>self.window.rootViewController = self.navigationController; dispatch_async(dispatch_get_global_queue(0, 0), ^{ [[[[tabBarController viewControllers] objectAtIndex:1] topViewController] init ]; [self.window addSubview:tabBarController.view]; [self.window makeKeyAndVisible]; });

Поведение этого состоит в том, что оно выполняет какую-то работу:

  1. Отображает Splash Default.png
  2. Показывает белый экран
  3. Наконец, отображается главное окно с вкладкой BarController.

Пожалуйста, помогите, потому что я знаю, что все делаю неправильно!

Ответы [ 2 ]

2 голосов
/ 20 октября 2011

Как сказал bbum, UIKit не является потокобезопасным.Вместо того, чтобы бросать инициализацию в фоновом режиме, спросите себя, какая часть замедляет инициализацию и работает оттуда.

Вы загружаете изображение из Интернета или анализируете какой-то файл?Это хорошие примеры того, что можно вернуть в фоновом режиме с помощью Grand Central Dispatch (по крайней мере, часть загрузки изображения должна отображаться в основном потоке).

Вместо переноса всейinit в диспетчере, попробуйте что-то вроде этого в методе init контроллера представления:

dispatch_async(queue, ^{
  [self doLoadData]
  dispatch_async(dispatch_get_main_queue(), ^{
    //Set new data to be displayed     
  });
});

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

1 голос
/ 20 октября 2011

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

Если класс и / или метод явно не задокументированы как поточно-ориентированные, то это не потокобезопасен .

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

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

Вы можете прочитать Руководство по программированию параллелизма для получения подробной информации.

...