【问题标题】:Weird NSOutlineView crash奇怪的 NSOutlineView 崩溃
【发布时间】:2019-03-21 17:08:52
【问题描述】:

我在 NSOutlineView 中遇到奇怪的崩溃:当我单击“折叠”按钮时,应用程序立即崩溃,甚至“异常断点”也无助于查看问题所在。

我尝试在没有调试器的情况下运行应用程序,并重现了该问题。一旦应用程序崩溃,我就有了 OSX 崩溃窗口,并且能够从那里提取崩溃消息:

The window has been marked as needing another Update Constraints in Window pass, but it has already had more Update Constraints in Window passes than there are views in the window

还有调用堆栈,但由于 libsystem_c.dylib 内部发生崩溃,它无济于事,所以我不在这里发布它。

似乎自动布局有问题。完全不知道接下来的步骤。请给我一个建议!

另外,还有一件事是在更新到 OSX Mojave 之后才开始的。

【问题讨论】:

  • 从 Xcode 菜单栏中,选择 Product > Scheme > Edit Scheme。在左侧列表中选择“运行”。然后选择右侧区域中的“诊断”选项卡。打开“Address Sanitizer”和“Zombie Objects”旁边的复选框。点击“关闭”。运行您的应用程序并尝试重现问题。您是否通过这些选项集获得了更多信息?
  • @robmayoff 没有。应用程序在我得到任何有用的调试信息之前就崩溃了。
  • 我也有同样的问题。你是怎么解决这个问题的?对于我来说,我有 NSTextView,当我在那里放一个长文本时它会崩溃。

标签: xcode macos cocoa autolayout


【解决方案1】:

经过数小时的调试和测试,我注意到该消息是由“无限布局循环”引起的。

与大纲视图相关的不同代码导致 NSSplitView 进行布局。并且委托方法- (CGFloat) splitView:(NSSplitView*)sender constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(NSInteger)dividerIndex 在崩溃之前已经被调用了大约 200 次。

很难捕捉到这个 bcs 它实际上不是无限递归,所以只是调试器并没有太大帮助。 我刚刚添加了帮助我识别问题的简单代码:

static int a = 0; NSLog(@"Layout: %d", a++);

希望我的经验对其他人有所帮助!

【讨论】:

  • My - (NSRect)splitView:(NSSplitView *)splitView effectiveRect:(NSRect)proposedEffectiveRect forDrawnRect:(NSRect)drawnRect ofDividerAtIndex:(NSInteger)dividerIndex 被无限调用。你是怎么解决这个问题的???
  • Mojave 的问题和错误消息完全相同,SplitView 的委托也有非常相似的无限循环。你是怎么解决这个问题的?
  • 原来我正在为 drawRect:dirtyRect 中的 Mojave 暗模式更新颜色,这导致 -(void)layout 中的无限循环。我删除了该代码,因为我不需要它,并且修复了它。
【解决方案2】:

我将构建更新到 IOS 14 和 Mac OS 20.15.6,错误消失了。

【讨论】:

    【解决方案3】:

    尝试关闭笔尖中的“使用自动布局”复选框(在文件检查器选项卡中)。 可能必须为每个视图禁用它。

    同样,不相关,但 Mojave 强制您使用核心动画。 我的大多数笔尖都关闭了“设置想要层”。 但是,在我的一个笔尖中,我选中了一个流浪的 setWantsLayer 复选框。 当我取消选中它时,视图(NSSearchField)正确绘制

    【讨论】:

    • 很遗憾,我无法关闭自动布局。我有几百个 XIB。而且我无法完全更新应用程序:(
    • 另外,没有让你了解 Core Animation。 Mojave 强制使用 CA 意味着什么?
    • 如果我使用 [[window contentView] setWantsLayer:YES] 启用核心动画,我重复的重新显示问题就会消失。如果我不启用核心动画,Apple 会记录奇怪的消息“错误:窗口已被标记为需要另一个显示窗口通道,但它已经有 3 个显示窗口通道。”另外,我注意到 Mojave 窗口被绘制在 CATransaction 内部,而不是旧的 [window displayIfNeeded] 路径。
    猜你喜欢
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 2023-02-02
    • 2016-10-27
    • 2018-03-06
    相关资源
    最近更新 更多