开发者

How to update a UILabel immediately?

I'm trying to create a UILabel which will inform the user of what is going on while he waits. However the UILabel always delay its text update until after the system goes idle again.

The process:

[infoLine performSelectorOnMainThread:@selector(setText:) withObject:@"Calculating..." waitUntilDone:YES];
[distanceManager calc]; // Parses a XML and does some calculations
[infoLine performSelectorOnMainThread:@selector(setText:) withObject:@"Idle" waitUnti开发者_C百科lDone:YES];

Should not waitUntilDone make this happen "immediately"?


If you are doing this on the main UI thread, don't use waitUntilDone. Do a setText, setNeedsDisplay on the full view, set a NSTimer to launch what you want to do next starting 1 millisecond later, then return from your function/method. You may have to split your calculation up into chucks that can be called separately by the timer, maybe a state machine with a switch statement (select chunk, execute chunk, increment chunk index, exit) that gets called by the timer until it's done. The UI will jump in between your calculation chunks and update things. So make sure your chunks are fairly short (I use 15 to 200 milliseconds).


Yes waitUntilDone makes the setText: happen immediately, but setting the label's text does not mean the screen is updated immediately.

You may need to call -setNeedsDisplay or even let the main run loop tick once before the screen can be updated.


Here's a useful function I added to a subclass of UIViewController. It performs the selector in the next run loop. It works, but do you think I should make NSTimer *timer an instance variable since it's likely this method will be called more than once.

- (void)scheduleInNextRunloopSelector:(SEL)selector {
    NSDate *fireDate = [[NSDate alloc] initWithTimeIntervalSinceNow:0.001]; // 1 ms
    NSTimer *timer = [[NSTimer alloc]
                      initWithFireDate:fireDate interval:0.0 target:self
                      selector:selector userInfo:nil repeats:NO];
    [fireDate release];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    [timer release];
}


Use performSelector:(SEL) withObject:(id) afterDelay:(NSTimeInterval):

self.infoLine.text = @"Calculating...";
[self performSelector:@selector(likeABoss) withObject:nil afterDelay:0.001];
//...
-(void) likeABoss {
    // hard work here
    self.infoLine.text = @"Idle";
}
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜