2012-01-03 58 views
4

我有一個相當慢(100-200ms)的drawRect方法。爲了節省時間,我需要緩存結果。我正在做這樣的實際緩存:在主線程上安排一個低優先級任務

// some code to check if caching would be desirable goes here. If it is desirable, then 
UIGraphicsBeginImageContext(viewSize); 
CGContextRef c = UIGraphicsGetCurrentContext(); 
[view.layer renderInContext: c]; 
UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); 
[self.cachedImageArray addObject:image]; 
UIGraphicsEndImageContext(); 

緩存本身可能需要長達40毫秒。這仍然是值得的。但是緩存必須等到所有東西都呈現出來,否則就會出錯。此外,緩存是一項低優先級任務。一旦顯示了所有內容,其他事情可能仍會繼續,如果是這樣,緩存可以等待。但由於它使用UIKit,它必須在主線程上。

而不是放在一些任意延遲,是否有一個防彈的方式來等待這樣?

+2

爲什麼緩存任務必須在主線程上?難道你不能只在主線程上發送(或顯示)結果(通過'performSelectorOnMainThread'或GCD的魔術'dispatch_async(dispatch_get_main_queue(),^ {});'並在接近結尾的單獨線程上分離緩存你的'drawRect'? – 2012-01-03 22:01:53

+3

從iOS 4開始,繪製圖形上下文是線程安全的,並且不必在主線程上執行,你可以使用'dispatch_async()'將這個事件踢到後臺線程。 – 2012-01-03 22:32:37

回答

1

高速緩存本身不必在主線程上完成。您可以獲取圖像上下文或位圖數據的副本/引用,並僅在渲染完成時才使用NSThread啓動它。示例:

- (void) drawRect:(CGRect)rect { 
    do_rendering_here(); 
    // when rendering completed: 
    NSThread *t = [[NSThread alloc] initWithTarget:self selector:@selector(doCaching:) object:c]; 
    [t start]; 
    [t release]; 
} 

- (void) doCaching:(CGContextRef)ctx { 
    // do whatever kind of caching is needed 
} 
+0

USing 'NSThread仍然被允許,但是蘋果公​​司在大多數任務中建議不要這樣做,他們更願意使用Grand Central Dispatch,並且使用@ MichaelDautermann的解決方案從他對這個問題的評論中查看Apple的併發指南:http://developer.apple。 com/library/ios /#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html – 2012-01-03 22:45:42

+0

對不起,我不是這些新的APIs,因爲我沒有任何支持iOS5的設備,一個由3.1.3頭文件構建的舊工具鏈... – 2012-01-03 22:47:56

+1

@ H2CO3 - GCD與iOS 4.0一起推出,因此它已經被支持了一段時間。另外,不需要對NSThread實例進行復雜的分配,以在後臺線程上執行某些操作。只需使用NSObject的'-performSelectorInBackground:withObject:'。 – 2012-01-05 19:47:50