tacos_tacos_tacos
tacos_tacos_tacos

Reputation: 10585

dispatch_async call in applicationDidFinishLaunchWithOptions not behaving the way I would expect

I'm totally new to threading in iOS. I have a tab bar based application with tabs as follows:

I want to go ahead and call that init method before I actually call tabBarController.selectedSegmentIndex = 1. So, I did this in my applicationDidFinishLaunching:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [Constants configureApp];

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];
});

The behavior of this is that it does kind of work in that it:

  1. Displays Splash Default.png
  2. Shows a white screen
  3. Finally shows the MainWindow with the tabBarController.

Please help because I know I'm doing it all wrong!

Upvotes: 0

Views: 1075

Answers (2)

Kevin
Kevin

Reputation: 3131

Like bbum said, UIKit is not thread safe. Instead of throwing the init in the background, ask yourself what part is making the init slower and work from there.

Are you loading an image from the web or parsing some file? Those are good examples of things that back be put in the background using Grand Central Dispatch (At least the download part of the image, the displaying should still be done in the main thread).

Instead of wrapping the entire init in a dispatch, try something like this in the init method of the view controller:

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

Be sure, when doing this, that the view looks okay without the data (and loads the data once downloaded gracefully) because it will be displayed before things are done downloading.

Upvotes: 2

bbum
bbum

Reputation: 162712

You can't arbitrarily dispatch various tasks to queues and have any hope that it'll work.

Unless a class and/or method is explicitly documented as being thread safe, then it is not thread safe.

As well, you must very carefully design your own classes to be thread safe. While queues make this easier to do, it is still rife with sharp edges.

In this case, you are futzing with UIKit objects off of the main queue. This is generally verboten outside of a few specific contexts.

You'll want to read the Concurrency Programming Guide for details.

Upvotes: 1

Related Questions