Ios 关联视图消失后调用的CATiledLayer drawInContext

Ios 关联视图消失后调用的CATiledLayer drawInContext,ios,calayer,catiledlayer,Ios,Calayer,Catiledlayer,今天我遇到了一个有趣的iOS问题,涉及到一个CATiledLayer。这只发生在设备上,而不是在模拟器上 我的视图通过drawLayer:inContext:delegate回调在其CALayer中绘制。此图层有一个CATiledLayer派生的子图层,该子图层在替代的drawInContext:方法中绘制自己的图形 这两个层都通过CGContextDrawPDFPage()呈现pdf内容。(CALayer绘制低分辨率版本,而CATiledLayer子层在顶部绘制高分辨率内容。) 我遇到了一个场

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

我的视图通过drawLayer:inContext:delegate回调在其CALayer中绘制。此图层有一个CATiledLayer派生的子图层,该子图层在替代的drawInContext:方法中绘制自己的图形

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

我遇到了一个场景,在这个场景中,我将对视图进行处理—将其从superview中删除并发布。在视图上调用dealloc()。稍后,系统将调用CATiledLayer的drawInContext:方法(在后台线程上)。它会吸引人,但从Springboard方法返回时会崩溃,这样做的话,我的应用程序也会崩溃

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


但我只能想象有一种更优雅的方式。为什么CATiledLayer drawInContext:方法在父层之后仍然被调用,并且父层的视图被取消分配?关闭视图以避免这种情况发生的正确方法是什么?

在释放视图之前,将
view.layer.delegate
设置为nil

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

更新:我记得,在旧版本的iOS中,当涉及CATiledLayers时,这方面存在问题,但是在dealloc之前将委托设置为nil现在是一个好办法。请参阅:

修复此问题的缓慢但最好的方法是同时设置
view.layer.contents=nil
。这将等待线程完成。

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

如果视图已解除分配,self.superview(对self的访问,解除分配的对象)如何工作?注意:TomSwift的评论涉及在解除分配中解除委托。这确实太晚了,答案在发布视图之前被编辑为零。Peter是正确的,这是唯一可靠的方法。它没有文档记录,但我编写了一个测试来确认它确实会阻塞,直到所有后台委托调用完成。如果绘图任务已在GCD中排队,则将委托设置为nil(上面接受的答案)不会起任何作用。