4

我今天遇到了一个有趣的 iOS 问题,涉及 CATiledLayer。这仅发生在设备上 - 而不是在模拟器中。

我的视图通过 drawLayer: inContext: 委托回调在其 CALayer 中绘制。该层有一个 CATiledLayer 派生的子层,它在重写的 drawInContext: 方法中进行自己的绘图。

两个图层都通过 CGContextDrawPDFPage() 呈现 pdf 内容。(CALayer 绘制低分辨率版本,而 CATiledLayer 子层在顶部绘制高分辨率内容。)

我遇到了一个场景,我将完成视图 - 将其从其超级视图中删除并释放它。在视图上调用 dealloc()。稍后,系统将调用 CATiledLayer 的 drawInContext: 方法(在后台线程上)。它会绘制,但是从 Springboard 方法返回时会崩溃,并且这样做也会导致我的应用程序崩溃。

我通过在 CATiledLayer 中设置一个标志来修复它,告诉它不再渲染,来自视图的 dealloc 方法。

但我只能想象有一种更优雅的方式。怎么在父层之后还是调用了 CATiledLayer drawInContext: 方法,而父层的视图被释放了?关闭视图以免发生这种情况的正确方法是什么?

4

4 回答 4

10

缓慢但最好的修复方法是也设置view.layer.contents = nil. 这等待线程完成。

于 2011-08-12T09:30:01.073 回答
3

view.layer.delegate在释放视图之前设置为零。

于 2011-02-09T09:53:12.090 回答
0
-(void)drawLayer:(CALayer *)calayer inContext:(CGContextRef)context {    
   if(!self.superview)
      return;
   ...

更新:我记得,当涉及到 CATiledLayers 时,旧版本的 iOS 中存在此问题,但现在可以在 dealloc 之前将委托设置为 nil。请参阅: https ://stackoverflow.com/a/4943231/2882

于 2011-03-31T15:29:41.617 回答
0

在这上面花了相当长的时间。我最新的方法是声明一个块变量并在 viewWillDisappear 方法中分配给 self。然后将 setContents 调用调用到全局调度队列 - 无需锁定主线程。然后当 setContents 将调用返回到主线程并将块变量设置为 nil 时,这应该确保视图控制器在主线程上被释放。不过需要注意的是,我发现使用 dispatch_after 来调用主线程是谨慎的做法,因为全局调度队列会保留视图控制器直到它退出其块,这意味着您可以在它退出(和释放)之间存在竞争条件视图控制器)和主线程块将块变量设置为 nil),这可能导致全局调度队列线程上的释放。

于 2013-05-10T11:48:43.353 回答