13
\$\begingroup\$

I have written this (truncated) code to fetch some tweets:

  dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

    NSString *JSONStr = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://search.twitter.com/search.json?q=haak&lang=nl&rpp=100"] encoding:NSUTF8StringEncoding error:nil];
    if (!JSONStr) {
      [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
      return;
    }

    /*... PARSING ETC ...*/

    dispatch_sync(dispatch_get_main_queue(), ^{
      [delegate didReceiveTweets:foundTweets];
    });

    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
  });

Note the lines from dispatch_sync(dispatch_get_main_queue(), ^{ to });. This will update the UI.

Is this the good way to do it, or are there better ways than using dispatch_sync within a dispatch_async? Or should I not do this at all? Should I also send setNetworkActivityIndicatorVisible: from within the main thread?

The reason I'm not using NSURLConnection is because this code comes from a class method, so I need to create an object containing the delegate for the NSURLConnection, which seems overkill to me.

\$\endgroup\$
8
\$\begingroup\$

you don't necessarily have to call -setNetworkActivityIndicatorVisible: from the main thread. I didn't find anything in the documentation about UIApplication not being thread safe, and since your application's main thread doesn't have anything in common with the system, you are free to call it whenever you like.

dispatch_sync: that's fine. you could also call dispatch_async, since i'm not really sure you would want do display the network indicator while the feeds are actually being set on the UI - instead you probably only want the downloading to be indicated. I would probably go for dispatch_async.

But to answer your question, that piece of code is perfectly fine ( with the minor addition that maybe you should really use only one exit point from your method ... )

Hope this helps.

\$\endgroup\$
  • \$\begingroup\$ But if the method makes any UI calls, it still needs to be called on the main thread. \$\endgroup\$ – JeremyP Apr 20 '12 at 10:33
5
\$\begingroup\$

Typically you want to perform UI interactions from the main thread, I would just move it to before the first dispatch_async call to turn it on. Then have it turn off in the later dispatch in the main_queue, so that it also happens on the main thread. This of course assumes that you were calling from the main thread to start with. If not you could just make another call to dispatch_async with the main_queue at the beginning.

\$\endgroup\$
1
\$\begingroup\$

Avoid to dispatch sync code on main queue. This can cause freezing because this code supposed to run on main thread will wait until main thread will be able to run it. In the same time this code will block main thread. Try always use:

dispatch_async(dispatch_get_main_queue(), ^{});

Also this is bad style to use direct numerical values of system constants. Try to use predefined values:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ .. });
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.