Change UILabel in loop
I want to ch开发者_JAVA技巧ange the UILabel after 2 sec in a loop. But current code change it to last value after loop finished.
- (IBAction) start:(id)sender{
for (int i=0; i<3; i++) {
NSString *tempStr = [[NSString alloc] initWithFormat:@"%s", @" "];
int randomNumber = 1+ arc4random() %(3);
if (randomNumber == 1) {
tempStr = @"Red";
}else if (randomNumber == 2) {
tempStr = @"Blue";
} else {
tempStr = @"Green";
}
NSLog(@"log: %@ ", tempStr);
labelsText.text = tempStr;
[tempStr release];
sleep(2);
}
}
Your code updates label to last value only as your function blocks main thread so UI cannot get updated. To solve that problem move your updating code to separate function and call it using performSelector:withObject:afterDelay:
method. (or schedule calls using NSTimer
)
Possible solution (you will also need to handle the case when user taps your button several times in a row, but that should not be too difficult):
- (IBAction) start:(id)sender{
[self updateLabel];
}
- (void) updateLabel{
static const NSString* allStrings[] = {@"Red", @"Blue", @"Green"};
static int count = 0;
int randomNumber = arc4random()%3;
NSString *tempStr = allStrings[randomNumber];
NSLog(@"log: %@ ", tempStr);
labelsText.text = tempStr;
++count;
if (count)
[self performSelector:@selector(updateLabel) withObject:nil afterDelay:2.0];
}
- (IBAction) start:(id)sender{
for (int i=0; i<3; i++) {
int randomNumber = 1+ arc4random() %(3);
NSString *tempStr = @"";
if (randomNumber == 1) {
tempStr = @"Red";
}else if (randomNumber == 2) {
tempStr = @"Blue";
} else {
tempStr = @"Green";
}
[labelsText performSelector:@selector(setText:) withObject:tempStr afterDelay:i * 2]
NSLog(@"log: %@ ", tempStr);
}
}
Don't use sleep()
to perform actions after a delay, it blocks the whole thread. Use performSelector:withObject:afterDelay:
instead. As you are probably running this on the main thread, sleep()
will block any UI updates until after the whole loop has run, so the only thing you see is the last update. As a general rule of thumb, assume that the UI doesn't ever get updated until after the app has finished executing your method.
You shouldn't use %s
as the format specifier for an NSString
, that's the format specifier for a C string. You should use %@
instead. In fact, if all you are doing is initialising the string with an NSString
literal, there's no need to use initWithFormat
at all, you can just use the literal itself.
You've also got big memory problems. At the beginning of the loop, you allocate memory for an instance of NSString
that is a single space. You then overwrite the pointer to this memory when you assign to tempStr
again, meaning you leak the original allocation of memory. Build and Analyze will find problems like this for you. Then you release tempStr
, but as the second assignment to this pointer variable was to an autoreleased NSString
, the instance will be released one time too many when the autorelease pool gets drained, which will probably manifest itself as a crash that's impossible to debug a little later in the app.
I'd do something like this:
- (void)showRandomColourAfterDelay {
static NSUInteger count = 0;
switch (arc4random()%3) {
case 0:
labelsText.text = @"Red";
case 1:
labelsText.text = @"Blue";
case 2:
labelsText.text = @"Green";
}
count++;
if (count >= 3) return;
[self performSelector:@selector(showRandomColourAfterDelay) withObject:nil afterDelay:3];
}
In fact, I'd probable use an NSArray
to hold the colour strings, but that would involve changes outside of a single method, so I've stuck with your hard-coding approach.
精彩评论