這個問題可能已經存在,但我找不到它。我的問題基本上是這樣的。如果我有一個重複的NSTimer執行某些比定時器間隔更長的事情,會不會有一些顛簸使應用程序崩潰?或者,直到執行任務完成後新的時間事件纔會啓動?NSTimer Thrashing - 我需要處理它嗎?
回答
由於的NSTimer運行在創建它的運行循環,我覺得它永遠不能再進入它調用的方法。這document on the run loops證實了這一點(見「定時器源」節:
「同樣,如果一個定時器啓動時運行的循環是在 中間執行處理程序,定時器等待下一次 直到通過運行循環調用其處理程序」
重複計時器總是根據預定的開火時間安排自己,而不是實際的開火時間。例如,如果定時器計劃在特定時間和之後每隔5秒觸發一次,則即使實際觸發時間延遲,計劃觸發時間也會始終以原來的5秒時間間隔進行。如果開火時間延遲至其通過一個或多個預定開火時間,則在該時間段內定時器僅被觸發一次;計時器在發射後將被重新安排在未來的下一個預定發射時間。
你可以隨時安排,僅出現一次一個NSTimer,然後函數結束時重新計劃。
- (void)myFunction {
......stuff that your method does
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(myFunction) userInfo:nil repeats:NO];
}
只要你避免踢出一些異步工作,你就會好起來的。如果異步調度任務的時間通常比調用定時器之間的時間間隔長,那麼可以備份該隊列。如果做動畫,即使動畫未完成,計時器也會啓動。
讓我提供兩個例子。對於這兩個例子,讓我們想象一下,我們創建了每秒觸發一次的計時器:
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(handleTimer:)
userInfo:@"tick"
repeats:YES];
第一個例子:假設我們有一些串行隊列:
self.queue = [[NSOperationQueue alloc] init];
self.queue.maxConcurrentOperationCount = 1;
此外,假設我們有一個NSTimer
處理程序確實是這樣的:
- (void)handleTimer:(NSTimer *)timer
{
NSLog(@"%s %@", __FUNCTION__, timer.userInfo);
[self.queue addOperationWithBlock:^{
NSLog(@"%s starting some slow process; has %d operations queued", __FUNCTION__, self.queue.operationCount);
// to simulate a slow process, let's just sleep for 10 seconds
sleep(10);
NSLog(@"%s done", __FUNCTION__);
}];
}
因爲計時器射擊每一秒,而且由於TI mer處理程序幾乎立即返回(因爲它所做的全部都是排隊後臺操作),到第一個排隊操作(需要10秒)完成並且第二個開始時,已經有10個操作位於該後臺隊列中。到第二個後臺操作完成時,當第三個操作啓動時,有19個操作排隊。它只會變得更糟,因爲NSTimer
處理程序將簡單地繼續調用,發射速度比較慢的後臺操作正在被排除在隊列之外。顯然,如果處理程序在當前隊列中同步執行了所有操作,但一切正常,並且沒有積壓,NSTimer
沒有「顛簸」。
第二個例子:這個問題的另一個例子是動畫。讓我們假設定時器處理方法做類似以下,將啓動一個移動10秒的動畫UIImageView
:
- (void)handleTimer:(NSTimer *)timer
{
NSLog(@"%s %@", __FUNCTION__, timer.userInfo);
[UIView animateWithDuration:10.0
animations:^{
self.imageView.frame = [self determineNewFrame];
}
completion:nil];
}
這是不行的(或者更準確地說,你會看到的後續調用即使先前的動畫未完成,定時器調用handleTimer
)。如果你要這樣做,你必須跟蹤動畫是否完成。你必須做一些事情,如:
- (void)handleTimer:(NSTimer *)timer
{
NSLog(@"%s %@", __FUNCTION__, timer.userInfo);
if (!self.animating)
{
NSLog(@"%s initiating another animation", __FUNCTION__);
[UIView animateWithDuration:10.0
animations:^{
self.animating = YES;
self.imageView.frame = [self determineNewFrame];
}
completion:^(BOOL finished){
self.animating = NO;
}];
}
}
你要麼必須做一些狀態標誌(就像我的布爾animation
標誌),以防止更多的動畫第一個完成之前,或只是不要使用重複的計時器,只是揭開序幕另一個定時器在completion
塊中的動畫類方法UIView
。
我想到的任務是用塊使用動畫來移動視圖。我擔心這些移動請求會導致日誌堵塞。我想我可以通過在比我需要的方式堆放更多請求的方式來測試它,並通過手勢或某事使計時器無效並觀察發生的情況。 –
是的,這可能是一個問題(因爲當你啓動一個動畫時,這個調用通常會立即返回並且動畫會在稍後發生)。是的,我會傾向於「無效」,但在那個時候,爲什麼還要考慮重複定時器。 – Rob
當我測試這個,實例化大量的視圖來壓力測試應用程序,看起來像是發生的是,視圖動畫的動畫變得不連貫。但它運行幾個小時而沒有看起來有問題。我現在有觀點在圈子裏移動。看起來如果這實際上是一個問題,那麼觀點會隨機地開始跳躍,但事實並非如此。 –
- 1. 我需要處理OpenId嗎?
- 2. 我需要一個處理程序嗎?
- 3. PayPal:pixel.gif - 我需要它嗎?
- 4. MVC3 StorageSessionStateProvider - 我需要它嗎?
- 5. 我真的需要代理來處理node.js嗎?
- 6. 需要處理
- 7. ROOT中的ClassImp預處理器宏 - 它真的需要嗎?
- 8. Heroku計劃需要處理Stripe Payments嗎?
- 9. Spring Transaction中需要異常處理嗎?
- 10. @UiHandler:委託處理程序需要嗎?
- 11. FileSystemWatcher處理後需要內存嗎?
- 12. [myproject] .dll.config文件 - 我需要它們嗎?
- 13. 最短Levenshtein距離?我需要它嗎?
- 14. SqlCeResultSet.Close - 我需要調用它嗎?
- 15. 處理Log4perl記錄器時,我不再需要它
- 16. 是我需要的批處理文件嗎?
- 17. 我需要一個控制器來處理這種情況嗎?
- 18. 我完成使用後需要處理表單嗎?
- 19. 我真的需要四核處理器來安裝SharePoint 2010嗎?
- 20. Autofac - 我需要在MVC global.asax中手動處理IContainer嗎?
- 21. 需要幫助NSTimer和UISegmentedControl
- 22. 我需要處理NumberFormationException或NaN爲BigDecimal
- 23. 我需要固定匿名代理嗎?
- 24. 它需要釋放AVCaptureVideoPreviewLayer嗎?
- 25. 如何處理多個NSTimer?
- 26. 我有一個JSON對象,它是在dymanic長度,需要處理它
- 27. 我需要鎖嗎?
- 28. 我需要BackgroundWorker嗎?
- 29. 我需要app.config嗎?
- 30. 我需要getJson嗎?
謝謝,但我的問題是重複定時器的理解之一,而不是尋找替代品。 –