是啥导致了这个错误? “CALayer 位置包含 NaN:[240 nan]”

Posted

技术标签:

【中文标题】是啥导致了这个错误? “CALayer 位置包含 NaN:[240 nan]”【英文标题】:What causes this error? "CALayer position contains NaN: [240 nan]"是什么导致了这个错误? “CALayer 位置包含 NaN:[240 nan]” 【发布时间】:2011-03-02 19:06:45 【问题描述】:

每当我旋转带有UITableView 的屏幕时,我都会看到这种情况发生。我发现它发生在UIViewController 中的willRotatedidRotate 方法调用之间,我的同事在其他地方也看到了它,通常是围绕旋转。它直到最近才开始发生,我们不知道应该如何处理它(谷歌搜索不会以确切的形式出现错误消息)。有没有其他人遇到过这种情况知道该怎么做?

【问题讨论】:

【参考方案1】:

(决定将其从 cmets 中取出并将其作为答案,因为我认为这是一个非常好的答案:)

哈!我也有一个 NaN 计算(div0)。关键调试辅助:有问题的消息是由 NSLog() 输出的,所以在 NSLog() 上设置一个断点并观察操作系统当时正在做什么。对我来说,它是 myUISlider.value = NaN。

设置断点:

XCode 3.x

CMD-SHIFT-Y(调试窗口。) 断点按钮。 “双击符号” 输入“NSLog”(不加引号。)

XCode 4.x

CMD-6(断点导航器。) “+”添加断点(左下角) 选择添加符号断点。 符号:NSLog 确认:完成。

XCode 5.x - 7.1(至少) (与 4.x 相同,除了断点导航器现在是 CMD-7。)

运行应用程序,观察它在 NSLog 上的中断,检查堆栈跟踪。

【讨论】:

这是关于这个异常的真正重要的答案。请务必注意,使用 CALayer 的组件可能会引发此异常,而我们 API 用户不知道它们的存在(感谢封装)。 很好,调试方法+1。 @Caio:如果你没有得到断点,(a)验证你的断点在 NSLog() 上中断(做一个测试日志),(b)你得到的错误可能是不是由 NSLog() 输出的;看看你能不能在别处休息。我的答案的关键是:因为我找不到要破解的代码,所以我破解了输出消息的位。也许在你的堆栈跟踪中查找一些 ios 异常处理代码并尝试打破它。 @Olie 终于知道到底发生了什么。除以零是由内部 UIScrollView 方法进行的,所以这就是断点在 NSLog 上没有中断的原因。有时一个约束可以是 0。 在 Xcode 8 中,我有一个 CALayer position contains NaNNSException 结尾。设置异常断点:所有异常都给了我堆栈跟踪。 (符号断点:NSLog 没有。)【参考方案2】:

我找到了问题。

当您重置tableview 的框架时,它会为表中的每一行调用委托方法tableView:heightForRowAtIndexPath:,以便它可以在需要时重新计算其内容大小。那时,我们做了一些特殊的处理来返回高度,并且由于我们的代码中的一些错误假设,我们错误地返回了NaN,因为除以零错误(我们除以的变量被假定永远不会为零) .确保我们不会在此处除以零。

【讨论】:

我遇到了同样的错误(位置和边界都包含 NaN,消息通常成对出现。)仅在我的视图显示之前。没有旋转,没有表格,没有花哨的计算。一个简单的深灰色视图,带有标签“处理中...”和进度指示器。还有其他人对此有想法吗? 在您的 viewdidload/viewwillappear 方法中放置一些断点,并确保您不会在任何地方意外除以零。 它可能相关也可能不相关,但我在 Mavericks OSX 10.9 中更一致地看到了这种崩溃,但在 OSX 10.9.2 更新后没有再次出现。 这让我更好地了解了我的项目中的问题...由于我使用单独的情节提要,我呈现的 viewController 有一个我没有发送正确值的 tableView到。【参考方案3】:

我花了一天时间试图找到导致相同问题的代码,并在 Xcode 中启用“异常中断”后一分钟内解决了它。检查this tutorial 以了解如何启用它。

【讨论】:

您能否附上页面内容的简短摘要?这样,这篇文章的未来读者可以快速轻松地获得他们正在寻找的信息。 @gobernador 我会的,因为它帮助了我!要找到您的应用程序死掉的确切行,请转到 xcode 左侧的断点选项卡,单击 +,添加新的 Exception Breakpoint 并将设置保留为默认值。点击完成并重新运行您的应用。【参考方案4】:

当我假设我遇到了这个问题:

tableView:heightForHeaderInSection: 返回了 NSInteger,但它返回了 CGFloat...

改变:

-(NSInteger)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

解决了我的问题。

编辑:

在某个时候,我弄清楚了计算机在 C 级别以下是如何工作的,所以我想我会分享它...(我将使用 x86_64 中的寄存器名称,因为我最熟悉它们,ARM 会略有不同,但类似的)

int f()
          float someFloat=5.0f;
          return someFloat;
       

导致将someFloat 的值转换为整数类型,然后将其复制到特定寄存器:%rax 然后调用返回指令。

float f()
          float someFloat=5.0f;
          return someFloat;
       

导致将someFloat 的值从其当前位置复制到特定寄存器:%xmm0,然后调用返回指令。

所以如果你有错误的原型,调用代码会认为值在错误的位置,你最终会返回一个垃圾值。

【讨论】:

【参考方案5】:

这个错误也让我花了很长时间。 最后我发现我的同事写了这样一段话:

UIEdgeInsets a;
a.left = (...some calculation);
button.imageEdgeInsets = a;

我像这样重写了这些代码并解决了这个问题:

UIEdgeInsets a;
a.left = (...some calculation);
a.top = 0;
a.bottom = 0;
a.right = 0;
button.imageEdgeInsets = a;

UIEdgeInsets 的某些值未正确初始化,有时会变成 NaN 值,导致应用程序崩溃。 更一般地说,您应该检查 C 风格结构的所有值是否都已正确初始化。

【讨论】:

【参考方案6】:

还有另一种重现问题的方法:在太小的矩形上使用insetBy(dx:dy:)

【讨论】:

【参考方案7】:

你可以试试这个yourTableview?.bounces = false。它对我有用。

【讨论】:

以上是关于是啥导致了这个错误? “CALayer 位置包含 NaN:[240 nan]”的主要内容,如果未能解决你的问题,请参考以下文章

调试 'CALayer 位置包含 NaN: [nan nan]'

未捕获的异常:CALayer 位置在做动画时包含 NaN

随机“CALayerInvalidGeometry 原因:CALayer 位置包含 NaN”异常

UIScrollView CALayer 位置包含 NaN

随机“CALayerInvalidGeometry原因:CALayer位置包含NaN”异常

是啥导致了这个推进错误?