jjzjj

关于iphone:在iOS上,如果CALayer的一个子类与一个空的显示方法一起使用,那么app似乎进入了无限循环?

codeneng 2023-03-28 原文

On iOS, if a subclass of CALayer is used with an empty display method, then app seems to go into infinite loop?

如果创建了一个单视图应用程序,其 FooViewUIView 的子类,然后执行一个

1
NSLog(@"hello");

in drawRect,然后打印出来。

如果我创建一个名为 CoolLayerCALayer 子类,并将这个方法添加到 FooView.m:

1
2
3
+(Class) layerClass {
    return [CoolLayer class];
}

FooView.mdrawRect的末尾,做一个

1
NSLog(@"layer's class is %@", self.layer.class);

然后 CoolLayer 被打印。所以现在视图的底层是 CoolLayer.

但是当将以下内容添加到 CoolLayer.m 时:

1
2
3
-(void) display {

}

这是自动调用以重绘图层的方法(类似于 drawRect),然后没有打印任何 NSLog。可能是应用程序进入了无限循环。 (即使我的 touchesBegan 打印出 NSLog 消息也没有打印)。如果在 display 处设置断点,它会停在那里一次,但是当我继续程序时,它永远不会再到达 display 处。这有什么问题,如何解决?


图层的显示方法不会被再次调用,除非图层是脏的,即设置为需要重新显示。这通常是一件好事,这就是为什么您不会看到该方法被多次调用的原因。

另外,display的正常实现会调用drawInContext:方法。由于您在子类中覆盖了它,因此永远不会调用视图的 drawRect: 方法。您需要复制 CALayer 的标准行为,或者在您自己的实现中调用超类的 display 方法。

  • 这真的很奇怪:如果我的 CoolLayer 的 display 是一个全空方法,那些 NSLog 不会被打印出来,而 touchesBegan 不会打印出 NSLog 消息,但是如果我将 [super display]; 添加到那个空的 display 方法,那么所有那些 NSLog 消息都将被打印出来
  • 是的,这和预期的一样。有关默认行为的信息,请参阅 Apple 的文档。
  • 哦,那是文档中的哪一部分?我的意思是,文档是否有声明说,如果未触摸 contents 或未调用 [super display],那么它将以某种方式挂起或不显示 NSLog 在其他方法中(例如在 UIView 中的 touchesBegan 中)
  • 另一个更新是,如果 [super display]; 被删除,但添加了一个 self.contents = (id) [uiimage CGImage];,那么图像将被显示,并且 NSLog 消息将在 FooView\\ 的 touchesBegan 方法中打印......但正在触摸或设置contents 强制?文档没有提到它必须设置....
  • 好的,我想我找到了未打印 touchesBegan 中的 NSLog 消息的原因:没有什么可触摸的。或者大小可能就像 (0,0),没有任何东西被触及,并且 touchesBegan 从未被调用过。但是我不遵循如果 display 为空,则永远不会调用 drawRect 的逻辑?我将 NSTimer 设置为每 1 秒重复一次到 [self.view setNeedsDisplay];,并调用 display,但不调用 drawRect
  • 请参阅 display 方法的"讨论"段落。它说明了默认行为(例如,您必须重新实现或以其他方式在子类中复制的行为),并提供有关如何实现它的建议。
  • 它是否提到在某些情况下不调用drawRect?我搜索了那个文档,它根本没有提到 drawRect ......另外,我怀疑 display 这样做:它可以将 contents 设置为 CGImage 对象,或者它启动一个 ImageContext,并通过它ImageContext 到 drawInContext,然后当它返回时,将该 ImageContext 转换为 CGImage,并将其设置为 contents ...我希望一些文档可以验证这一点,还有,为什么即使 NSTimer 设置了 drawRect 现在也不调用使用 setNeedsDisplay 查看?


这听起来不像是无限循环。如果您处于无限循环中,您的应用程序将冻结,几秒钟后,跳板应用程序会因无响应而终止它。

在您的图层上调用 setNeedsDisplay 或 setNeedsDisplayInRect 以使其"脏"并要求再次绘制。请注意,您不必再调用 setNeedsDisplay,因为重新渲染图层并将其内容推送到屏幕上需要大量工作。仅在某些内容发生更改时显示


您在这里没有看到无限循环。如果你是,正如 Duncan 指出的那样,你最终会因为看门狗定时器或无限递归而崩溃,这在你在调试器中看到的堆栈跟踪中会立即显而易见。

如果您将 NSLog 放入 UIView 的 -drawRect: 方法中,然后使用您自己的自定义 CALayer 覆盖其默认图层类,该 CALayer 会进行自己的绘图,您的 UIView 的 -drawRect: 将不再被调用。绘图现在将由您的自定义支持层处理。

如核心动画编程指南的"通过子类化提供 CALayer 内容"小节中所述,如果您想以某种方式自定义图层的 contents CGImageRef,您通常会在 CALayer 中覆盖 -display。通常,如果您想在 CALayer 中渲染自定义 Quartz 绘图,您将覆盖 -drawInContext:。使您被覆盖的 -display 方法完全空白,并且不向 contents 属性写入任何内容,这不是标准行为,所以我对您看到这样做的奇怪结果并不感到惊讶。

根据您最近提出的一系列问题,我强烈建议您停下来花一些时间阅读 Core Animation Programming Guide 并查看一些涉及 CALayers 的示例代码,然后再继续。

  • 我想我找到了奇怪的原因:没有设置图像,也没有什么可触摸的......但在我在这里看到你的答案之前,我发布了另一个问题,可能描述了 displaydrawInContext 的工作原理。 .但不确定它如何不会调用drawRect:stackoverflow.com/questions/10791025/...。我想在我理解之后,我对 CALayer 如何缓存图像、setNeedsDisplay 如何真正工作以及如何调用 drawRect 有了一个很好的了解

有关关于iphone:在iOS上,如果CALayer的一个子类与一个空的显示方法一起使用,那么app似乎进入了无限循环?的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  3. ruby - 树顶语法无限循环 - 2

    我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He

  4. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  6. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  7. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  8. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  9. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  10. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

随机推荐