首页 > 解决方案 > SwiftUI 上下文菜单是否使用 LayoutConstraints?

问题描述

我假设 SwiftUI 不再使用 NSLayoutConstraints。但是我在控制台中遇到约束错误。任何人都知道如何调试?

当我打开上下文菜单时,如果使用列表视图打印以下内容:

2019-12-09 10:52:52.029091-0700 ContextMenuTest[26384:13138419] [LayoutConstraints] 无法同时满足约束。以下列表中的至少一个约束可能是您不想要的。试试这个:(1)查看每个约束并尝试找出您不期望的;(2) 找到添加了一个或多个不需要的约束的代码并修复它。(注意:如果您看到不理解的 NSAutoresizingMaskLayoutConstraints,请参阅 UIView 属性 translatesAutoresizingMaskIntoConstraints 的文档)( "", "= 44 (active, names: groupView.actionsSequence...:0x7fd98781de00 )>", "", "", "", "")

将尝试通过打破约束 = 44 来恢复(活动,名称:groupView.actionsSequence...:0x7fd98781de00)>

在 UIViewAlertForUnsatisfiableConstraints 创建一个符号断点以在调试器中捕获它。中列出的 UIView 上的 UIConstraintBasedLayoutDebugging 类别中的方法也可能会有所帮助。

struct ContentView: View {
    var body: some View {
        List {
            Text("one")
            Text("two")
                .contextMenu(menuItems: {
                    Text("test")
                })
        }
    }
}

标签: swiftui

解决方案


我假设 SwiftUI 不再使用 NSLayoutConstraints。

这根本不是真的。SwiftUI如果您检查视图层次结构,仍然使用UIKit组件,并且大多数组件没有暴露的约束。但是一些“桥接”视图在底层具有NSLayoutConstraints它们的基UIView类。

一些组件(如警报、弹出框和上下文菜单)也会看到您的问题,因为这些组件很复杂,因此尚未完全移植。

对 使用符号断点UIViewAlertForUnsatisfiableConstraints

po UIApplication.shared.windows.first?.constraints

UIWindowUIViewhttps://developer.apple.com/documentation/uikit/uiwindow的子类。

根宿主控制器及其子视图没有任何限制,因为它们已完全移植到 SwiftUI 新的环境变量语法。

po UIApplication.shared.windows.first?.rootViewController?.view.constraints

SwiftUI 的许多运行时库仍然具有NSLayoutConstraints. 请参阅:上下文菜单警报视图等。

请注意,您需要切换到主堆栈框架才能访问UIApplication.shared( AppDelegate)。见下文:

调试导航器片段

如何检查视图层次结构?

使用dump, 允许您查看 SwiftUI 信息(比 po 更多):

po dump(UIApplication.shared.windows.first?.rootViewController)

为控制器列出了 UIKit 桥接类,例如

contextMenuBridge: Optional(<_TtGC7SwiftUI17ContextMenuBridgeV33Demo11ContentView_: 0x600002c8c720>)
      ▿ some: <_TtGC7SwiftUI17ContextMenuBridgeV33Demo11ContentView_: 0x600002c8c720> #81
        - super: NSObject
        ▿ host: Optional(<_TtGC7SwiftUI14_UIHostingViewV33Demo11ContentView_: 0x7fccd7403690; frame = (0 0; 414 896); autoresize = W+H; gestureRecognizers = <NSArray: 0x6000006f0d20>; layer = <CALayer: 0x6000008b5180>>)
          ▿ some: <_TtGC7SwiftUI14_UIHostingViewV33Demo11ContentView_: 0x7fccd7403690; frame = (0 0; 414 896); autoresize = W+H; gestureRecognizers = <NSArray: 0x6000006f0d20>; layer = <CALayer: 0x6000008b5180>> #0
        ▿ presentedMenuID: SwiftUI.ViewIdentity
          - seed: 0
        - interaction: nil
        - cachedPreferences: 0 elements
        ▿ seed: empty
          - value: 0
        - currentPreference: nil
        - cachedPlatformActions: 0 elements
        - cachedPreview: nil
    - accessibilityEnabled: false
    - cachedAccessibilityNodes: 0 elements
    - accessibilityNeedsUpdate: true
    - scrollTest: nil
    - delegate: nil
    - parentAccessibilityElement: nil

可以为警报、工作表和其他“桥接”类找到类似的窗口约束。

使用以下方法修复错误:

UIApplication.shared.windows[0].translatesAutoresizingMaskIntoConstraints = false

但是请注意,一旦 SwiftUI 成熟并退出测试版,这些桥梁可能会被删除。


推荐阅读