关联视图消失后调用 CATiledLayer drawInContext

发布于 2024-09-29 05:04:05 字数 604 浏览 8 评论 0原文

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

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

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

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

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

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

I ran into an interesting iOS problem today involving a CATiledLayer. This only happend on the device - not in the simulator.

My view draws in its CALayer via the drawLayer: inContext: delegate callback. This layer has a CATiledLayer-derived sublayer, which does its own drawing in an overridden drawInContext: method.

Both layers are rendering pdf content via CGContextDrawPDFPage(). (The CALayer draws a low res version, while the CATiledLayer sublayer draws hi-res content over the top.)

I ran into a scenario where I would be done with the view - would remove it from its superview and release it. dealloc() is called on the view. Sometime later, the CATiledLayer's drawInContext: method would be called (on a background thread), by the system. It would draw, but on return from the method Springboard would crash, and in doing so, bring down my app as well.

I fixed it by setting a flag in the CATiledLayer, telling it not to render anymore, from the view's dealloc method.

But I can only imagine there is a more elegant way. How come the CATiledLayer drawInContext: method was still called after the parent layer, and the parent-layer's view were deallocated? What is the correct way to shut down the view so this doesn't happen?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

北方。的韩爷 2024-10-06 05:04:06

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

The slow, but best way to fix is to also set view.layer.contents = nil. This waits for the threads to finish.

凉宸 2024-10-06 05:04:06

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

Set view.layer.delegate to nil before releasing the view.

爱要勇敢去追 2024-10-06 05:04:06
-(void)drawLayer:(CALayer *)calayer inContext:(CGContextRef)context {    
   if(!self.superview)
      return;
   ...

更新:据我所知,在旧版本的 iOS 中,当涉及到 CATiledLayers 时,存在问题,但在 dealloc 之前将委托设置为 nil 现在是正确的方法。请参阅:https://stackoverflow.com/a/4943231/2882

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

UPDATE: As I recall, there were problems with this in older versions of iOS when it came to CATiledLayers, but setting the delegate to nil before dealloc is now the way to go. See: https://stackoverflow.com/a/4943231/2882

风筝有风,海豚有海 2024-10-06 05:04:06

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

Spent quite a long time on this. My latest approach is to declare a block variable and assign to self in viewWillDisappear method. Then invoke the setContents call onto a global dispatch queue - no need to lock up the main thread. Then when setContents returns invoke back on to the main thread and set the block variable to nil, which should ensure that the view controller is released on the main thread. One caveat though, I have found that it is prudent to use dispatch_after for the invoke onto the main thread as the global dispatch queue retains the view controller until it exits its block, which means you can have a race condition between it exiting (and releasing the view controller) and the main thread block setting the block variable to nil) which could lead to deallocation on the global dispatch queue thread.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文