2010-10-27 57 views
4

我遇到了一個涉及CATiledLayer的有趣的iOS問題。這隻發生在設備上 - 不在模擬器中。在關聯視圖消失後調用了CATiledLayer drawInContext

我的視圖通過drawLayer:inContext:delegate回調來繪製它的CALayer。該圖層具有一個CATiledLayer派生的子圖層,該圖層在重寫的drawInContext:方法中執行自己的繪圖。

兩層都通過CGContextDrawPDFPage()渲染pdf內容。 (CALayer繪製低分辨率版本,而CATiledLayer子圖層則在頂部繪製高分辨率內容。)

我遇到了一個場景,我將完成視圖 - 將其從超級視圖中移除並釋放它。在視圖上調用dealloc()。稍後,系統會調用CATiledLayer的drawInContext:方法(在後臺線程上)。它會畫,但從Springboard崩潰的方法返回,並且這樣做,也會導致我的應用程序。

我通過在CATiledLayer中設置一個標誌,從視圖的dealloc方法中告訴它不再渲染來修復它。

但我只能想象有一種更優雅的方式。爲什麼CATiledLayer的drawInContext:方法仍然在父層之後被調用,並且父層的視圖被釋放了?關閉視圖的正確方法是什麼,所以這不會發生?

回答

0
-(void)drawLayer:(CALayer *)calayer inContext:(CGContextRef)context {  
    if(!self.superview) 
     return; 
    ... 

更新:我記得,有在舊版iOS的這一問題,當它來到CATiledLayers,但委託設置爲nil,前dealloc的是現在要走的路。請參閱:https://stackoverflow.com/a/4943231/2882

+0

這對我來說非常好,簡單而有效。 – 2011-09-12 09:02:27

+4

如果視圖已經被釋放,self.superview(一個自我訪問,一個釋放對象)如何工作? – 2012-09-11 08:26:31

3

在發佈視圖之前將view.layer.delegate設置爲零。

+0

我已經這樣做了。謝謝。 – TomSwift 2011-02-09 22:34:02

+0

注意:TomSwift的評論是關於在dealloc中委託委託。這確實爲時已晚,並且在釋放視圖之前將答案編輯爲無代表*。 – Danra 2012-09-12 06:12:09

9

緩慢但最好的修復方法是設置view.layer.contents = nil。這等待線程完成。

+1

彼得是正確的,這是做這件事唯一可靠的方法。它沒有記錄,但我寫了一個測試,以確認它確實阻塞,直到所有的後臺代表調用完成。如果繪圖任務已經在GCD中排隊,則將代表設置爲零(上面接受的答案)不會執行任何操作。 – Crufty 2013-12-06 04:22:17

0

在這花了相當長的時間。我最近的做法是聲明一個塊變量並在viewWillDisappear方法中指定給self。然後調用setContents調用到全局調度隊列中 - 不需要鎖定主線程。然後,當setContents返回調用主線程並將塊變量設置爲nil時,應確保視圖控制器在主線程上釋放。但有一點需要注意,我發現使用dispatch_after調用主線程是明智的,因爲全局調度隊列保留視圖控制器直到它退出它的塊,這意味着你可以在它退出(並釋放視圖控制器)和主線程塊將塊變量設置爲零),這可能導致全局調度隊列線程上的重新分配。