我還沒有看過反彙編看看,但我們正在使用一個稍微不同的解決方案。將CATiledLayer.content
屬性設置爲nil
塊,並強制所有排隊的渲染塊完成。這可以安全地踢到後臺線程,然後釋放UIView
可以被踢回主線程讓視圖和圖層dealloc。
下面是UIViewController dealloc
實現的一個示例,它將保持您的擁有視圖的活動時間足夠長,以在不阻止主線程的情況下安全停止呈現。
- (void)dealloc
{
// This works around a bug where the CATiledLayer background drawing
// delegate may still have dispatched blocks awaiting rendering after
// the view hierarchy is dead, causing a message to a zombie object.
// We'll hold on to tiledView, flush the dispatch queue,
// then let go of fastViewer.
MyTiledView *tiledView = self.tiledView;
if(tiledView) {
dispatch_background(^{
// This blocks while CATiledLayer flushes out its queued render blocks.
tiledView.layer.contents = nil;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// Make sure tiledView survives until now.
tiledView.layer.delegate = nil;
});
});
}
}
這是一個猜測,但有些蘋果的框架/班(StoreKit,CATiledLayer,UIGestureRecognizer)聲稱有@property (weak) id delegate
實現,但顯然不正確處理weak
委託。看着一些反彙編,他們正在嚴格執行種族限制if != nil
檢查,然後直接觸摸弱財產。正確的方法是申報一個__strong Type *delegate = self.delegate
,這將成功,並給你一個有力的參考保證生存,或nil
,但它肯定不會給你一個殭屍對象的參考(我的猜測是框架代碼尚未升級到ARC)。
在引擎蓋下,CATiledLayer
創建了一個調度隊列來完成後臺渲染,並且似乎以不安全的方式觸摸代理屬性,或者獲得本地引用,但沒有使其成爲一個強大的引用。無論哪種方式,如果委託被取消分配,派發的渲染塊將愉快地向殭屍對象發送消息。只是清除代表是不夠的 - 它會減少崩潰的數量,但不能安全地消除它們。
設置content = nil
執行dispatch_wait並阻塞,直到所有現有的排隊渲染塊完成。我們反彈回主線程以確保dealloc
是安全的。
如果有人有改進建議,請讓我知道。
我沒有找到適當的解決方案,但解決方法可以防止崩潰。最後把if(self.tiling == YES && [self.view superview]!= nil)放入 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx方法。自動平鋪設置是在視圖從超級視圖中移除之前設置的,或者在您的情況下,在方向更改之前設置。您可以通過對所有方向進行一個視圖來避免此問題。我的解決方法可以防止崩潰,但不會阻止CATiledLayer訪問圖像或以某種神祕的方式鎖定圖像。最終結果是無法從文件系統中刪除所述圖像。祝你好運! – TheBlack 2011-05-16 12:33:53