Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do SwiftUI Context Menus use LayoutConstraints?

Tags:

swiftui

I was under the assumption that SwiftUI no longer uses NSLayoutContstraints. However I am getting constraint errors in console. Anyone have any idea how to debug?

The following prints out if with the list view when I open the context menu:

2019-12-09 10:52:52.029091-0700 ContextMenuTest[26384:13138419] [LayoutConstraints] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) ( "", "= 44 (active, names: groupView.actionsSequence...:0x7fd98781de00 )>", "", "", "", "" )

Will attempt to recover by breaking constraint = 44 (active, names: groupView.actionsSequence...:0x7fd98781de00 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in may also be helpful.

struct ContentView: View {
    var body: some View {
        List {
            Text("one")
            Text("two")
                .contextMenu(menuItems: {
                    Text("test")
                })
        }
    }
}
like image 585
wshamp Avatar asked Dec 09 '19 17:12

wshamp


1 Answers

I was under the assumption that SwiftUI no longer uses NSLayoutContstraints.

This is simply not true. SwiftUI still uses UIKit components if you inspect the view hierarchy, and most components do not have exposed constraints. But some "bridged" views have NSLayoutConstraints for their base UIView classes under the hood.

Your issue is also seen by some components like alerts, popovers and context menus, as these are complex and so have not been fully ported.

Using a symbolic breakpoint for UIViewAlertForUnsatisfiableConstraints:

po UIApplication.shared.windows.first?.constraints

(UIWindow is a subclass of UIView) https://developer.apple.com/documentation/uikit/uiwindow.

The root hosting controller and its subviews have no constraints as they have been fully ported to SwiftUI new Environment Variable syntax.

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

Many runtime libraries of SwiftUI still have NSLayoutConstraints. See: context menu, alert view and so on.

Note you need to switch to the main stack frame in order to be able to access UIApplication.shared (AppDelegate). See below:

Debug Navigator snippet

How to inspect the view hierarchy?

Using dump, allows you to see the SwiftUI info (more than po):

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

The UIKit bridging classes are listed for the controller, e.g

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

Similar window constraints can be found for alerts, sheets and other "bridged" classes.

Fix the error using:

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

Note however that these bridges may be removed once SwiftUI matures and comes out of beta.

like image 139
Pranav Kasetti Avatar answered Nov 02 '22 20:11

Pranav Kasetti