2012-03-29 95 views
27

在带有ARC的ios5.0中,在我的rootviewcontroller中,我调用由应用程序委托持有的安全管理器对象中的方法。在该方法中,我设置如下的计时器:NSTimer未触发选择器

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self 
             selector:@selector(updateModel:) userInfo:str repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 

但是,这决不会触发选择器即, updateModel:永远不会被调用。什么可能是错的?有没有另一种更有效的方式,我可以做到这一点,而不使用NStimer?

回答

10

你似乎有点混淆你的计时器变量。

你初始化一个新的计时器,但你并没有真正使用它。你想使用你初始化的定时器还是你想要的ApplicationDelegate.timer?

以下是两种可能的解决方案。

方案一(假设你有名为ApplicationDelegate一个类的实例,并且它具有定时属性):

ApplicationDelegate.timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(updateModel:) userInfo:str repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:ApplicationDelegate.timer forMode:NSRunLoopCommonModes]; 

方案二:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(updateModel:) userInfo:str repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 
+0

对不起ab在帖子中列出错误..我已经编辑它以反映我正在做的事情。我正在使用你提到的第二种方式......它仍然无法正常工作。 – inforeqd 2012-03-29 02:56:01

+20

第二种方法是不正确的。它试图添加计时器两次。 'scheduledTimerWithTimeInterval:...'已经添加了计时器。确保你在主线程上运行这个。 – 2012-03-29 02:59:33

+0

有没有办法找出定时器被添加到哪个线程?我认为这是我将它添加到主线程... – inforeqd 2012-03-29 03:03:02

5

此行有几个问题:

[[NSRunLoop currentRunLoop] addTimer:ApplicationDelegate.timer forMode:NSRunLoopCommonModes]; 

首先,它不应该是必需的。 -scheduledTimerWithTimeInterval:...已将计时器添加到runloop。你不需要再添加它。

其次,本地变量timer与属性ApplicationDelegate.timer(此时推测为nil)无关。

如果您正在与应用程序委托说话太多以至于您创建了一个名为ApplicationDelegate(全局宏?)的东西,那么您就是在讨论它太多。应用程序委托是应用程序的委托;它协助应用程序启动和停止并响应系统事件。应用程序委托不是存储全局变量的地方。在任何情况下,计时器绝对不是您从另一个对象获取的东西。

+0

对这篇文章中的错误感到抱歉..我已经编辑它以反映我正在做这件事的方式....它仍然无法正常工作。关于您对使用应用程序委托的评论..我有一个在解析Web服务响应后创建的模型。我必须保留应用程序中所有视图的模型。因此,我认为该模型应该由应用程序委托人持有,否则我不知道还有哪些地方可以保留它以供所有视图使用。 – inforeqd 2012-03-29 02:55:41

+1

您可以在构建模型时将模型传递给视图控制器,也可以将模型对象放入单例中。你不应该把它们挂在应用程序代理上。这使得代码重用非常困难,并且使得应用程序委托(它具有与存储数据无关的独立函数)复杂化。 – 2012-03-29 02:58:29

8

我赶上了同样的问题,我火计时器在主队列来解决这个问题:

[NSURLConnection sendAsynchronousRequest:request queue:_operationQueue 
    completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){ 
     [self loopUpUpdateStart]; 
}]; 

-(void)loopUpUpdateStart{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 

     _loopTimerForUpRevision = 
      NSTimer scheduledTimerWithTimeInterval: kNetworkLoopIntervalUpRev 
              target: self 
             selector: @selector(myCoolMethod) 
             userInfo: nil 
             repeats: YES]; 
     TRACE(@"Start Up updates"); 
    }); 
} 
105

也可能是一个线程的问题:

如果

[NSThread isMainThread] 

是假的再启动像这样的计时器:

dispatch_async(dispatch_get_main_queue(), ^{ 
     timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(tick:) userInfo:nil repeats:YES]; 
    }) 
+0

+1,谢谢......这个伎俩! – Joe 2013-12-27 00:17:27

+1

谢谢!你能解释一下线程问题吗? – JohnH 2015-02-26 01:14:07

+4

定时器仅在主(UI)线程中正确执行。如果您尝试在除主线程之外的另一个线程中启动计时器,则它不会触发。 – tmanthey 2015-02-26 08:00:03