Tuesday, May 3, 2011

How do I update the UI in the middle of this thread?

Below is a block of code that runs in a separate thread from my app's main thread. How do I get the UI to update after each button gets its thumbnail? Right now it doesn't update until the whole method finishes. The buttons are already added to a UIScrollView.

(LotsGridButton is just a UIButton with some extra properties.)

- (void)fetchThumbnails {
    CCServer* server = [[CCServer alloc] init];
    for (int i=0; i<[buttons count]; i++) {
     LotsGridButton* button = [buttons objectAtIndex:i];  
     if (button.lot.thumbnail) continue;
     // load the thumbnail image from the server
     button.lot.thumbnail = [server imageWithPath:button.lot.thumbnailURL];
     [button setImage:button.lot.thumbnail forState:UIControlStateNormal];
    }
    [server release];
}
From stackoverflow
  • I've no experience with the iPhone but in Cocoa in general you're supposed to update the UI only from the main thread.

    From a different thread you can execute code in the main thread by using NSObject's:

    performSelectorOnMainThread:withObject:waitUntilDone:
    
  • In place of setImage:forState:, take a look at the performSelectorOnMainThread: method, e.g.:

    [myButton performSelectorOnMainThread:@selector(setThumbnail:) withObject:[server imageWithPath:myButton.lot.thumbnailURL] waitUntilDone:NO];
    
    lawrence : sweet! it worked, once I made a wrapper method (since performSelector only takes one arg and setImage:forState: takes 2). is this an instance of a general pattern, like "change the widget in the main thread and it'll show its changes right away"?
    Alex Reynolds : On the iPhone, at least, UI updates take place on the main thread. You can't reliably update widgets from background threads. So by running a method on the main thread that performs UI updates, you're more likely to get faster UI updates.

0 comments:

Post a Comment