2009-11-14 40 views
9

我想在當前方法通過並且UI已更新後執行方法。爲此,我現在使用[object performSelector:@selector(someSelector) withObject:someObject afterDelay:0.0]。根據Apple's documentation,這將創建一個NSTimer,然後觸發並將選擇器追加到當前的NSRunLoop。但我不認爲這很優雅。有一種簡單的方法可以直接將選擇器排入當前運行循環,而不需要Cocoa創建一個Timer等。將選擇器排入運行循環 - 是[NSObject performSelector:withObject:afterDelay:]要走的路嗎?

performSelectorOnMainThread:withObject:waitUntilDone:(如果我在主線程)或performSelector:onThread:withObject:waitUntilDone:waitUntilDone:NO做我想做的開銷更少?

歡呼和預先感謝

MrMage

回答

6

可可是事件驅動的。您不會「在當前運行循環中排列選擇器」。簡單地說:發送給應用程序(用戶輸入,計時器,網絡活動...)的事件會導致運行循環運行,這會導致循環運行中發生事件。當然有「細節」,但這是最基本的行爲。

如果您想延遲執行某個選擇器到當前運行循環的末尾,請最後調用它,或要求它在即將到來的循環運行(非常接近)運行。 -performSelector:...方法正確的做法。他們創造了一個計時器,導致事件發生。

欲瞭解更多信息,請參閱Cocoa Event-Handling Guide

+1

我所引用的文件讀取「期間執行當前線程上的指定選擇下一個運行循環週期和可選的延遲時間之後。'這不意味着選擇器必須排入下一個運行循環嗎? – MrMage 2009-11-14 17:27:05

+0

當然可以。 :-)這是通過定時器觸發事件​​。 – 2009-11-14 18:05:40

+0

接受這一個是因爲它讓我對真正發生的事情有了最深入的瞭解。 – MrMage 2009-11-14 22:00:41

4

我沒有看到任何關於-performSelector:withObject:afterDelay:你突出顯示的方法。該方法簡單地將當前循環運行循環完成後要執行的任務排隊。從documentation in the section you linked to

在下一運行 循環週期和一個可選的延遲 週期之後執行所述 當前線程上的指定選擇器。因爲它會一直等到 下一個運行循環週期才能執行 選擇器,所以這些方法會從 當前執行的代碼提供 自動迷你延遲。多個 排隊選擇器按排列順序執行一個接一個 ,排列順序爲 。

不創建NSTimer對象來管理它,選擇器被簡單地排隊以便在一定的延遲(小延遲意味着在運行循環週期結束後立即執行)之後運行。對於在發生UI更新後希望發生的操作,這是最簡單的技術。

如需更清晰的線程排隊,您可以查看NSOperationsNSOperationQueues。 maxConcurrentOperationCount爲1的NSOperationQueue可以按順序依次運行操作。

+0

其確實建立了定時器:http://developer.apple.com/mac/library/documentation/cocoa/reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelector :withObject:afterDelay: '此方法設置一個計時器以在當前線程的運行循環中執行aSelector消息。定時器配置爲以默認模式運行(NSDefaultRunLoopMode)。當定時器觸發時,線程將嘗試從運行循環中出列消息並執行選擇器。「# – MrMage 2009-11-14 22:02:58

+0

你們都是正確的。 -performSelector:withObject:afterDelay:使用核心基礎計時器API,而不是NSTimer實例。 – NSResponder 2009-11-15 01:07:41

+1

只是想補充一點,類似的外觀[self performSelector:<#(SEL)#> withObject:<#(id)#>]不會等到運行循環的下一次運行,而是立即調用該方法。這是顯而易見的,但我仍然把它放在那裏。 – SayeedHussain 2013-09-26 18:28:33

2

我已經使用這個技術很多次我自己,我不認爲這是不雅......但是,你可以嘗試另一種方法是:

performSelectorOnMainThread:withObject:waitUntilDone:NO

只是因爲你已經在主線程,並不意味着它不會工作(其實文件中引用的行爲從主線程調用時會發生)......,我認爲這將有相同的行爲當waitUntilDone設置爲NO時,它排隊執行選擇器的請求,並在當前運行循環結束時運行。

+0

我在自己的文章中寫過關於... – MrMage 2009-11-14 22:01:56

+0

嗯,我的歉意 - 我想我最後錯過了。這是一個更好的方式來做你想做的事情。 – 2009-11-15 05:21:49

4

我更喜歡NSRunLoop方法 「performSelector:目標:參數:順序:模式:」。它的保證,直到運行循環的下一次迭代不執行選擇,你不必更動指定任意延遲等