如何刷新UI线程上的button?

在我的用户界面上有一个button,每按下一次button,我就会每隔800毫秒闪一下(打开,然后再closures)。 我用下面的代码做到这一点:

- (void)flickEmergencyButton { // Check whether an emergency is in progress... if (model.emergencyInProgress) { // ...and if so, flick the state self.emergencyButton.selected = !self.emergencyButton.selected; // Make this method be called again in 800ms [self performSelector:@selector(flickEmergencyButton) withObject:nil afterDelay:0.8]; } else { // ...otherwise, turn the button off self.emergencyButton.selected = NO; } } 

…除了以下function外,其他function都能正常工作:在用户界面上还有一个UIScrollView,当用户将手指放在上面并滚动时,button会冻结。 虽然我完全明白这是为什么,我不知道该怎么办。

performSelector:withObject:afterDelay消息调度要在当前线程(即主线程)上发送的消息,即。 用户界面踩踏,因此不会处理消息,直到所有其他用户界面活动结束。 正确? 但我需要在UI线程上这样做,因为我不能select/取消任何其他线程上的button,对不对? 那么这里的解决scheme是什么?

我会build议使用核心animation。 尝试这样的事情:

 -(void) flash{ [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.3f]; [UIView setAnimationCurve:UIViewAnimationCurveLinear]; if( emergency ){ // Start flashing [UIView setAnimationRepeatCount:1000]; [UIView setAnimationRepeatAutoreverses:YES]; [btn setAlpha:0.0f]; }else{ // Stop flashing [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationRepeatCount:1]; [btn setAlpha:1.0f]; } emergency = !emergency; [UIView commitAnimations]; } 

btn被声明为

 @property(nonatomic, retain) IBOutlet UIButton *btn; 

紧急情况是一个简单的BOOLvariables。

调用闪光灯开始并停止animation。

在这个例子中,为了简单起见,我们给alpha属性设置了animation,但是你可以像按照Sam的回答一样使用button背景颜色,或者你喜欢的任何属性。

希望能帮助到你。

更新:

关于在两个图像之间进行转换,请尝试调用imageFlash而不是flash

 -(void) imageFlash{ CABasicAnimation *imageAnimation = [CABasicAnimation animationWithKeyPath:@"contents"]; [btn setImage:normalState forState:UIControlStateNormal]; if( emergency ){ imageAnimation.duration = 0.5f; imageAnimation.repeatCount = 1000; }else{ imageAnimation.repeatCount = 1; } imageAnimation.fromValue = (id)normalState.CGImage; imageAnimation.toValue = (id)emergencyState.CGImage; [btn.imageView.layer addAnimation:imageAnimation forKey:@"animateContents"]; [btn setImage:normalState forState:UIControlStateNormal]; // Depending on what image you want after the animation. emergency = !emergency; } 

normalStateemergencyState是你想要使用的图像:

声明为:

 UIImage *normalState; UIImage *emergencyState; 

分配图像:

 normalState = [UIImage imageNamed:@"normal.png"]; emergencyState = [UIImage imageNamed:@"alert.png"]; 

祝你好运!

虽然这感觉像是一个CoreAnimation的工作(也许animation的自定义UIControlbackgroundColor ),你可以用一个NSTimer在适当的运行循环模式下运行来实现这一点。

 NSTimer *timer = [NSTimer timerWithTimeInterval:0.8f target:self selector:@selector(flicker:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 

而当你想停止animation:

 [timer invalidate], timer = nil; button.selected = NO; 

通过将计时器添加到所有NSRunLoopCommonModes ,您不仅可以将其添加到默认的运行循环模式,而且还可以在用户交互持续处理模式( UITrackingRunLoopMode )中将其添加到模式中。

一般来说, 苹果的文档给出了运行循环模式和运行循环的更全面的解释。