2012-03-29 93 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