views:

789

answers:

2

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];
}
+3  A: 

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:
diciu
+4  A: 

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];
Alex Reynolds
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"?
lawrence
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.
Alex Reynolds