【问题标题】:NSTimer not working calling UIButton setHidden:YES/NONSTimer 无法调用 UIButton setHidden:YES/NO
【发布时间】:2012-10-24 19:02:09
【问题描述】:

我不明白为什么这不起作用。我试图在计时器周期被击中时显示 lblstatus:

-(void) viewDidAppear:(BOOL)animated
{
        [NSTimer scheduledTimerWithTimeInterval:1
                                         target:self
                                       selector:@selector(TimeForPictureCycle)
                                       userInfo:nil
                                        repeats:NO];
}

-(void)TimeForPictureCycle
{
    while(YES)
    {
        [lblStatus setHidden:NO];
        sleep(2);
        [lblStatus setHidden:YES];
        sleep(3);
    }
}

【问题讨论】:

  • 可能是一个愚蠢的问题,但我经常忽略它,您是否将 XIB/Storyboard 中的引用设置为标签?
  • 永远不要在主线程上调用 sleep!
  • 是的,它连接到 IBoutlet 和 nib,我可以在任何事件中毫无问题地 setHidden
  • 永远不要从后台线程调用 UIKit 方法!
  • 无论如何这只会冻结你的应用程序。while (YES), sleep?

标签: iphone ios xcode ipad cocoa


【解决方案1】:

您在主线程上调用sleep(),这意味着在您将标签设置为hidden 后,该线程会暂停并阻止运行循环继续,因此它无法更新您的用户界面。您当前的代码简单地阻塞了您的整个应用程序。

你可以这样做:

-(void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.showTimer = [NSTimer scheduledTimerWithTimeInterval:1
                                         target:self
                                       selector:@selector(showLabel)
                                       userInfo:nil
                                        repeats:NO];
}

-(void)showLabel
{ 
    [lblStatus setHidden:NO];
    self.hideTimer = [NSTimer scheduledTimerWithTimeInterval:2
                                         target:self
                                       selector:@selector(hideLabel)
                                       userInfo:nil
                                        repeats:NO];
}

-(void)hideLabel
{        
    [lblStatus setHidden:YES];
    self.showTimer = [NSTimer scheduledTimerWithTimeInterval:3
                                         target:self
                                       selector:@selector(showLabel)
                                       userInfo:nil
                                        repeats:NO];
}


- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self.showTimer invalidate];
    [self.hideTimer invalidate];
}

【讨论】:

  • 这样更好,但它仍然会导致问题:当多次调用 viewDidAppear 时,可能会有多个计时器。更好地将计时器存储在实例变量中,以便您可以取消它。
  • 你也可以使用[self performSelector:@selector(hideLabel) withObject:nil afterDelay:1.0]; 而不是使用 NSTimers
  • 你的权利,我已经更新了我的答案。我更喜欢使用NSTimer 而不是performSelector: 我不知道具体原因,这只是个人喜好。
  • 顺便说一句,你也可以取消 performSelector:[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideLabel) object:nil]
  • 我知道[[NSRunLoop currentRunLoop] cancelPerformSelector:@selector(hideLabel) target:self argument:nil]; 是另一种取消它的方式。
【解决方案2】:

你可以简单地做到这一点:

-(void)viewDidAppear:(BOOL)animated {
    [lblStatus performSelector:@selector(setHidden:) withObject:0 afterDelay:1];
    [lblStatus performSelector:@selector(setHidden:) withObject:@1 afterDelay:3];
}

我不太确定为什么我可以将 0 作为对象传递,但它确实有效。

【讨论】:

  • 我喜欢简单,但它只执行一次。问题中的代码暗示它应该重复运行。
  • 顺便说一句:你可以传递0,因为在这种情况下它被视为nil,所以它会调用[lblStatus setHidden:nil],然后再次被视为[lblStatus setHidden:NO]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
相关资源
最近更新 更多