2011-09-22 49 views
13

UIView有一個setNeedsDisplay方法,可以在相同的事件循環內多次調用,在重繪工作很快就會發生的情況下是安全的,只有一次。是否有一種簡單的方法(在Cocoa/iOS中)將方法調用排隊以在下一個運行循環中運行一次?

是否有這種行爲的通用機制可可?一種說法是:「根據需要多次排隊選擇器,當時間到了,選擇器將運行一次&清除隊列。」

我知道我可以在我的目標或NSOperationQueue中進行某種狀態跟蹤。我只是想知道我是否錯過了一種輕量級的方法。

(當然,答案可能是「不」。)

+0

@Bavarious我已經使用UIKit作爲例子,但我認爲這個問題一般適用於可可,不是嗎? –

+0

也許吧。如果您確定Mac OS X上的每種方法都適用於您的問題,請隨時添加可可標籤。 – 2011-09-22 16:37:34

回答

12

setNeedsDisplay是不是你描述的一個很好的例子,因爲它實際上不運行每次調用它。它只是設置一個標誌。但問題很好。

一個解決方案是使用NSNotificationQueueNSNotificationCoalescingOnName

另一個解決方案是建立一個蹦牀來做你自己的聯合。我沒有一個非常好的蹦牀博客參考,但這裏有一個例子(LSTrampoline)。如果你想在一段時間內合併消息,建立這個並不難。我曾經建造了一個蹦牀類似一個forwardInvocation:這樣:

- (void)forwardInvocation:(NSInvocation *)invocation { 
    [invocation setTarget:self.target]; 
    [invocation retainArguments]; 
    [self.timer invalidate]; 
    self.timer = [NSTimer scheduledTimerWithTimeInterval:self.timeout invocation:invocation repeats:NO]; 
} 

這實際上聚結,對象在時間段的所有郵件(不只是匹配的郵件)。這就是我需要的特殊問題。但是你可以擴展這個來跟蹤哪些選擇器正在合併,並檢查你的調用以查看它們是否「足夠」匹配。

爲了得到這個對未來事件循環運行,只是超時設置爲0。

我一直意在博客上寫下蹦牀。所需先令:我upcoming book涵蓋了第4和第20蹦牀

+2

夢幻般的答案,我認爲NSNotificationCoalescingOnName正是我所期待的。 :-) –

6
[NSObject cancelPreviousPerformRequestsWithTarget:self 
             selector:@selector(doTheThing:) 
              object:someObject]; 
[self performSelector:@selector(doTheThing:) 
      withObject:someObject 
      afterDelay:0]; 

這不正是如何UIView這樣做是因爲setNeedsDisplay簡單地設置一個標誌和內部UIView機制確保建立之後調用drawRect:繪圖環境,但這是一種通用的方式,並且不需要在您的班級中進行任何特殊的狀態跟蹤。

+1

請注意,對'cancelPreviousPerformRequest ...'的調用可能非常慢。在很多情況下,這很好,但如果經常打電話,這可能是一個問題。 –

相關問題