2013-09-30 94 views
1

是否有辦法觸發NSNotification(可能會觸發相當數量的工作)而不延遲任何當前完成的代碼?在沒有延遲當前操作的情況下觸發NSNotification

具體來說,我有一個UIPanGestureRecognizer,它允許用戶平移數月,一月,二月等。一旦用戶舉起他們的手指(識別器狀態改變UIGestureRecognizerStateEnded),有一些清理代碼運行,包括一些用戶界面一個框架等),以及 - 重要的是 - 在選定月份觸發的NSNotification。

這可以在模擬器中順利運行,但是當在我的iPhone 4上運行時,性能非常糟糕(即當我擡起手指時,UI鎖定時間爲+1.5秒)。如果我刪除通知,則表現會恢復良好。請注意,這些通知正在整個應用中發送(同步一個基於月的日曆,一個基於星期的日曆和一個事件列表),並且直到現在都沒有顯示性能問題。只有當它們與手勢識別器一起使用時,性能才成爲問題。

+2

你真的應該使用Instruments工具並運行Time Profiler模塊來查看代碼真正拖延了多久。對我來說,這聽起來像是某些操作阻止了主UI線程,而不是在其自己的線程中運行。但沒有時間限制,只是猜測而已。 – ExitToShell

回答

1

首先,您應該進行簡介以確定究竟花了些什麼時間。無論是現在還是延遲了1.5秒的延遲時間都很長,直到將來有一段時間。

當您發佈通知時,會立即進行廣播和處理。您可以做的最好方法是使用GCD或performSelector:withObject:afterDelay:(其中delay爲0)在runloop的下一次迭代中發佈通知。

+0

嘗試performSelector:withObject:afterDelay:有0個延遲,但未解決初始性能問題。另請參閱我的答案。 –

+1

你真的需要用儀器進行分析,以確定所有時間/阻塞的情況...... – Wain

0

將dispatch_async()與performSelectorOnMainThread結合使用:withObject:waitUntilDone:是「在不延遲當前操作的情況下觸發NSNotification」的一種解決方案。 NSNotificationQueue可能是另一種解決方案,但我沒有發現它與dispatch_async一樣有效。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^{ 
    [self performSelectorOnMainThread:@selector(performNotification:) withObject:someObject waitUntilDone:NO]; 
}); 

- (void)performNotification:(SomeClass*)someObject 
{ 
    [[NSNotificationCenter defaultCenter] postNotificationName:MyNotificationName object:someObject]; 
} 

(通過此SO article

+0

請不要發佈對您的問題的編輯作爲答案。 – paulrehkugler

+0

這是爲了回答主要問題。我重新編寫它以使其更清楚。 –

1

使用NSNotificationQueue。這是最簡單的方法。

+0

我以前沒有用過它 - 只是在文檔和書中閱讀它,但這似乎是迄今爲止最好的答案。 「NSNotificationQueue」是直接爲@David James問題而建立的。我完全不同意這些評論者的說法 - 平移手勢識別器將在短時間內發射數百個動作,因此通過加速解決性能問題並不一定是可行的。 @ mbachrach的解決方案也是解決性能問題的正確方法:做*少*工作,不多工作更快。 – MaxGabriel

+0

我試過NSNotificationQueue enqueueNotification:使用postStyle NSPostIdle和NSPostASAP,但仍然被阻止。只有我發現沒有阻止的事情是dispatch_async/performSelectorOnMainThread(在我的答案^)。另外,我傾向於贊同@MaxGabriel,它可能是泛姿態識別器(位於UIGestureRecognizerStateChanged塊中)導致處理帶寬的備份。當它到達通知時,操作系統必須趕上。我會首先關注。 –

相關問題