2

I'm implementing a simple twitter client for the iPhone using a UITableView. I fetch the picture of each twitter user in my feed when their cell appears in tableView: cellForRowAtIndexPath:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    UIImage *profileImage = [tweet.user getProfileImageDataInContext:self.fetchedResultsController.managedObjectContext];
    dispatch_async(dispatch_get_main_queue(), ^{
        cell.imageView.image = profileImage;
    });
});

Here is the code to fetch the image:

    if (!self.profileImage) 
{
    sleep(2);
    self.profileImage = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.profileImageURL]];
    //// if we recently scheduled an autosave, cancel it
    [TwitterUser cancelPreviousPerformRequestsWithTarget:self selector:@selector(autosave:) object:context];
    // request a new autosave in a few tenths of a second
    [TwitterUser performSelector:@selector(autosave:) withObject:context afterDelay:0.2];
}
return [UIImage imageWithData:self.profileImage];

Here is the error I'm getting:

twitterClient[10743:15803] bool _WebTryThreadLock(bool), 0x59bac90: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...

I think it's also worth mentioning that this happens when I scroll through the tableview very quickly when it hasn't been populated yet.

I would like the main UI to update upon completion of the download. The actual twitter app for iPhone does this quite well.

Any suggestions?

toddbranch
  • 82
  • 6
  • 1
    Can you show us the call that crashes? Hopping onto the main thread (via the main queue if you're doing this with GCD) to push an image should be correct. – Tommy Aug 10 '11 at 22:52
  • Thanks, Tommy. I edited the question with my actual calls and the crash. – toddbranch Aug 11 '11 at 04:45

2 Answers2

4

What’s the crash? A pretty standard pattern for things like this is

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // do background stuff
    dispatch_async(dispatch_get_main_queue(), ^{
        // do main-queue stuff, like updating the UI
    });
});
Noah Witherspoon
  • 57,021
  • 16
  • 130
  • 131
1

You're using GCD fine, your crash is happening because you're calling dataWithContentsOfURL in a background thread, which is not thread safe.

See: Does -dataWithContentsOfURL: of NSData work in a background thread?

Community
  • 1
  • 1
Sahil
  • 1,268
  • 12
  • 19