使用嵌套 UINavigationController 和 UITabBarController 弹出视图控制器时,Xcode 9 / iOS 11“CALayer bounds contains N

Posted

技术标签:

【中文标题】使用嵌套 UINavigationController 和 UITabBarController 弹出视图控制器时,Xcode 9 / iOS 11“CALayer bounds contains NaN: [nan 0; nan 0]”【英文标题】:Xcode 9 / iOS 11 "CALayer bounds contains NaN: [nan 0; nan 0]" when popping view controller with nested UINavigationController and UITabBarController 【发布时间】:2017-09-21 14:25:21 【问题描述】:

我正在为 Xcode 9、Swift 4、ios 11 和 iPhone X 更新我的应用程序。它似乎一直相对顺利,但每当我点击后退按钮时,我的应用程序就会崩溃。我可以毫无问题地前进 3-4 个屏幕,但第一个后退按钮总是会使应用程序崩溃。它不需要模拟器作为 iPhone X 运行。

它似乎没有深入到我在堆栈跟踪中的代码,所以我认为这是我正在弹出的视图控制器的重绘阶段,但我不确定。

由于 UITableViews 和 UIViews 周围有自定义阴影,我做了很多自定义绘图,因此我在除以变量的所有位置设置断点,但没有任何内容受到影响。所以这似乎不是我的代码以零计算。

*** Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer bounds contains NaN: [nan 0; nan 0]'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010af711cb __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010a8d3f41 objc_exception_throw + 48
    2   CoreFoundation                      0x000000010afe5b95 +[NSException raise:format:] + 197
    3   QuartzCore                          0x0000000109424424 _ZN2CA5Layer10set_boundsERKNS_4RectEb + 230
    4   QuartzCore                          0x0000000109414c29 -[CALayer setBounds:] + 251
    5   UIKit                               0x0000000107267439 __27-[_UILabelLayer setBounds:]_block_invoke + 80
    6   UIKit                               0x000000010726717b -[_UILabelLayer _setFrameOrBounds:settingAction:] + 23
    7   UIKit                               0x00000001072673d8 -[_UILabelLayer setBounds:] + 155
    8   QuartzCore                          0x000000010941537c -[CALayer setFrame:] + 630
    9   UIKit                               0x0000000107267319 __26-[_UILabelLayer setFrame:]_block_invoke + 80
    10  UIKit                               0x000000010726717b -[_UILabelLayer _setFrameOrBounds:settingAction:] + 23
    11  UIKit                               0x00000001072672b8 -[_UILabelLayer setFrame:] + 155
    12  UIKit                               0x0000000106c4cf1e -[UIView(Geometry) setFrame:] + 368
    13  UIKit                               0x0000000106e4ec40 -[UILabel setFrame:] + 141
    14  UIKit                               0x0000000106fff254 -[UIButton _layoutTitleView] + 248
    15  UIKit                               0x0000000106fff3cf -[UIButton layoutSubviews] + 250
    16  UIKit                               0x0000000106c6c551 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1331
    17  QuartzCore                          0x000000010941b4ba -[CALayer layoutSublayers] + 153
    18  QuartzCore                          0x000000010941f5a9 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 401
    19  QuartzCore                          0x00000001093a81cd _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 365
    20  QuartzCore                          0x00000001093d3ae4 _ZN2CA11Transaction6commitEv + 500
    21  UIKit                               0x0000000106b97f4a _UIApplicationFlushRunLoopCATransactionIfTooLate + 167
    22  UIKit                               0x00000001074ef960 __handleEventQueueInternal + 6894
    23  CoreFoundation                      0x000000010af142b1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    24  CoreFoundation                      0x000000010afb3d31 __CFRunLoopDoSource0 + 81
    25  CoreFoundation                      0x000000010aef8c19 __CFRunLoopDoSources0 + 185
    26  CoreFoundation                      0x000000010aef81ff __CFRunLoopRun + 1279
    27  CoreFoundation                      0x000000010aef7a89 CFRunLoopRunSpecific + 409
    28  GraphicsServices                    0x00000001104e59c6 GSEventRunModal + 62
    29  UIKit                               0x0000000106b9dd30 UIApplicationMain + 159
    30  My Customer's Application Name      0x000000010475f087 main + 55
    31  libdyld.dylib                       0x000000010cfedd81 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

【问题讨论】:

【参考方案1】:

TL;DR:在我们的例子中,这个 iOS 11 / Xcode 9 错误是由将自定义 UILabel 添加到 UINavigationItem.titleView 的代码引起的。

这段代码是使用臭名昭著的混合技术编写的,该技术覆盖了-[UINavigationItem setTitle:] 选择器 - 除了调用原始setTitle: 方法外,我们的开发人员还将具有相同标题的自定义标签设置为UINavigationItem.titleView 属性。问题是当导航项使用setTitle:nil 调用时,空的UILabel 被添加到具有零矩形尺寸的.titleView,这导致UIKit 崩溃。如果title: 参数为nil,则立即的快速修复是停止设置.titleView。长期的解决办法是从应用程序中移除 swizzling。

附:我打开了一个雷达,请求改进此错误的错误消息:

Xcode 9: Please improve error handling: -[UILabel setFrame:] and -[CALayer setFrame:] throws unfriendly exception if given a malformed CGRect

【讨论】:

以防万一我们在升级到 Xcode 9 时在应用程序的同一部分遇到另一个问题:***.com/questions/46409420/…。 非常有趣。所以它可能与操作工具栏有关。有趣的是,我要重新进入的屏幕还不需要工具栏。稍后我会进行更多测试,但目前客户也认为大标题并不那么漂亮。 人们似乎比我自己的回答更赞成你的回答,所以我给你解决方案。 嗯,你的回答给了我一个提示,所以这两个答案都有助于最终的知识。因此,我不知道应该接受哪个答案。可以是我的也可以是你的。谢谢!【参考方案2】:

由于我在修复它时已经完成了所有输入(将您的问题表达给其他人总是有帮助的;-))我决定发布我的问题和答案。

我有一个导航设置,其中标签栏嵌套在导航控制器中。我知道我们被警告过不要这样做,但是嘿,它一直像魅力一样起作用。通过外观代理设置大标题视图后,如下所示:

    if #available(iOS 11.0, *) 
        UINavigationBar.appearance().prefersLargeTitles = true
    

回到屏幕时屏幕开始崩溃。改回false,所有问题都消失了。

【讨论】:

嘿Departamento B,我们遇到了同样的崩溃,但设置略有不同。非常感谢您提示它可能与 UINavigationBar.appearance() 有关。 嗨@StanislavPankevich 很高兴听到它有帮助。你的情况发生了什么? 我们至少有 3 个不同的问题,目前只解决了其中的 1 个。完成后我们会写一个答案。 我已经发布了关于我们案例的答案。【参考方案3】:

我遇到了同样的问题,因为工具栏标题在以前的 VC 上设置为空字符串。一旦我用至少某种文本设置了所有标题,我就不再崩溃了。同样,这仅适用于 iOS 11 和 Xcode 9,在以前的版本中有效。

【讨论】:

嗯,或者可能是一个空的后退按钮或替换标题的 UIView? 哦,顺便说一句,这也是大标题还是普通标题? 这是一个带有空文本的 UILabel,也许我的答案不清楚。所以用 UIView 替换没有用。但也没有任何工具栏文本我得到这个错误。非常奇怪的行为。我最长的标题是大约 10 个文本,大标题没有任何问题【参考方案4】:

当我使用 NavigationBar 设置一个指定的 ViewController 时,我发生了这种情况,并且更喜欢大标题 = true。

我用 pjapple15 的方法解决了这个问题。我只是在前一个 ViewControllerNavigationBar 中设置了一个类似空字符串 = " " 的标题,并且效果很好。

我还在 NavigationBar.titleView 中添加了一个 SearchBar, 之后我只是设置了 NavigationItem.title = " "。

【讨论】:

以上是关于使用嵌套 UINavigationController 和 UITabBarController 弹出视图控制器时,Xcode 9 / iOS 11“CALayer bounds contains N的主要内容,如果未能解决你的问题,请参考以下文章

viewController 出现时出现黑色

UINavigationController & SplitViewController

UINavigationController

UINavigationController 风格

全屏显示 ViewController

多控制器