开发者

view hierarchy refresh timing

I'm trying to add a progress meter, or other "I'm busy right now" notification开发者_Python百科 to my view hierarchy right before doing some intense computation that will block the UI. My code looks some thing like:

//create view
[currentTopView addSubView:imBusyView];

//some initialization for the intense computation
[computation startComputing];

Unfortunately, my progress meter doesn't display until after the computation completes. It appears like the views aren't re-drawn until the run loop completes. I'm pretty sure that setNeedsDisplay and setNeedsLayout will also wait until the run loop completes.

How do I get the view to display immediately?


Redrawing only occurs when your code returns control to the run loop. So the easiest way would be for you to schedule the startComputing call with a zero delay. That way, it will be executed during the next run loop iteration (right after redrawing):

[computation performSelector:@selector(startComputing) withObject:nil afterDelay:0.0];

Be aware, though, that unless you do your computation in another thread you will not be able to update the UI during the computation.


If you are doing heavy calculations maybe spawning a new thread is a good idea.

Here I have an activityIndicator displayed and starts a large XMLParse operation in a background thread:

- (void) setSearchParser {
 activityIndicator = [[ActivityIndicatorView alloc] initWithActivity];
 [self.view addSubview:activityIndicator];
 [NSThread detachNewThreadSelector:@selector(getSearchResults:) toTarget:self withObject:[searchParser retain]];
}

then the getSearchResults method:

- (void) getSearchResults: (SearchResultParser *) parser {
 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 [parser startParser];
 [self performSelectorOnMainThread:@selector(searchResultsReady:) withObject:[parser data] waitUntilDone:NO];
 [pool release];
}

So firstly make a new thread:

[NSThread detachNewThreadSelector:@selector(getSearchResults:) toTarget:self withObject:[searchParser retain]];

this means that all code inside the getSearchResults will be executed on a different thread. getSearchResults also get's passed a parameter of "searchParser" thats a large object that just needs startParse called on it to begin.

This is done in getSearchResults. When the [parser startParser] is done, the results is passed back to the main thread method called "searchResultsReady" and the threads autorelease pool is released.

All the time it took from my parser began to it had finished, a gray view covered the screen an an activityIndicator ran.

You can have the small activityIndicator class I wrote:

-(id) initWithActivity {
 [self initWithFrame:[self bounds]];
 [self setBackgroundColor:[UIColor blackColor]];
 [self setAlpha:0.8];
 activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
 activityView.center = CGPointMake(160, 240); 
 [self addSubview:activityView ];
 [activityView startAnimating];
 return self; 
}

- (void) dealloc {
 [activityView release];
 [super dealloc];
}

Hope it helps you out, even though threads seems a bit confusing, they can help to make the UI not freeze up, which is especially important on the iPhone.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜