使用嵌套 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 的方法解决了这个问题。我只是在前一个 ViewController 的 NavigationBar 中设置了一个类似空字符串 = " " 的标题,并且效果很好。
我还在 NavigationBar.titleView 中添加了一个 SearchBar, 之后我只是设置了 NavigationItem.title = " "。
【讨论】:
以上是关于使用嵌套 UINavigationController 和 UITabBarController 弹出视图控制器时,Xcode 9 / iOS 11“CALayer bounds contains N的主要内容,如果未能解决你的问题,请参考以下文章