【问题标题】:SwiftUI NavigationView navigationBarTitle LayoutConstraints issueSwiftUI NavigationView navigationBarTitle LayoutConstraints 问题
【发布时间】:2021-03-26 17:09:03
【问题描述】:

这可能与最近发布的 XCode 新 (12.3) 版本有关,但我有一个非常简单的 SwiftUI 视图:

import SwiftUI

struct HomeView: View {
    var body: some View {
        NavigationView {
            Text("Text")
                .navigationBarTitle("My Title")
        }
    }
}

我在控制台中收到此警告:

2020-12-15 18:25:06.506062-0800 Shopmatic[46177:9585655] [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. 
(
    "<NSLayoutConstraint:0x600003636d00 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x7faf15d0dc30]-(6)-[_UIModernBarButton:0x7faf15c17500'Your Lists']   (active)>",
    "<NSLayoutConstraint:0x600003636d50 'CB_Trailing_Trailing' _UIModernBarButton:0x7faf15c17500'Your Lists'.trailing <= _UIButtonBarButton:0x7faf15c16140.trailing   (active)>",
    "<NSLayoutConstraint:0x600003631e50 'UINav_static_button_horiz_position' _UIModernBarButton:0x7faf15d0dc30.leading == UILayoutGuide:0x600002c18ee0'UIViewLayoutMarginsGuide'.leading   (active)>",
    "<NSLayoutConstraint:0x600003631ea0 'UINavItemContentGuide-leading' H:[_UIButtonBarButton:0x7faf15c16140]-(0)-[UILayoutGuide:0x600002c18e00'UINavigationBarItemContentLayoutGuide']   (active)>",
    "<NSLayoutConstraint:0x600003617160 'UINavItemContentGuide-trailing' UILayoutGuide:0x600002c18e00'UINavigationBarItemContentLayoutGuide'.trailing == _UINavigationBarContentView:0x7faf15e10000.trailing   (active)>",
    "<NSLayoutConstraint:0x600003632580 'UIView-Encapsulated-Layout-Width' _UINavigationBarContentView:0x7faf15e10000.width == 0   (active)>",
    "<NSLayoutConstraint:0x600003617520 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x600002c18ee0'UIViewLayoutMarginsGuide'](LTR)   (active, names: '|':_UINavigationBarContentView:0x7faf15e10000 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600003636d00 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x7faf15d0dc30]-(6)-[_UIModernBarButton:0x7faf15c17500'Your Lists']   (active)>

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

这个简单的例子看起来不错,但是当我做一些更复杂的事情时:

import SwiftUI

struct ListDetailView: View {
    var list: List
    
    var body: some View {
        NavigationView {
            Text("Detail View")
            .navigationBarTitle("Detail View Title")
            .navigationBarTitleDisplayMode(.large)
            .navigationBarItems(
                trailing:
                    Button(action: {
                        print("Button Pressed")
                    }) {
                        Image(systemName: "ellipsis")
                }
            )
        }
    }
}

导航标题区域布局完全搞砸了:

【问题讨论】:

  • 我有同样的问题,我对 swiftui 中的约束一无所知,我在想我们终于解决了这个约束问题,我们又来了,哈哈,也许 @asperi 有一个想法
  • 不推荐使用 .navigationBar 方法。在 14.3 中,这可能是很多问题的根源。 developer.apple.com/documentation/swiftui/view/…
  • @loremipsum 但是如果您检查代码并尝试一下,它不是!问题出在 navigationBarTitle
  • @goddamnyouryan 我试过了,不行尝试删除navigationBarTitle 你会发现问题消失了,所以问题出在navigationBarTitle

标签: ios swift swiftui


【解决方案1】:

它与NavigationBarTitle 无关。 .navigationTitle 未被弃用。似乎整个问题主要在于新的 Xcode 12.4 更新,即使是简单的代码:

var body: some View {
        NavigationView{
            Text("Hopefully will work this time")
                .navigationTitle("Error with constains")
        }
    }

添加.navigationViewStyle(StackNavigationViewStyle()) 修复问题

var body: some View {
        NavigationView{
            Text("Yes it does!")
                .navigationTitle("Wow it works")
        }
    }.navigationViewStyle(StackNavigationViewStyle())

附言。我的第一个 stackoverflow 回复 xD

【讨论】:

  • 老兄,这就是答案!我已经搜索了几个星期了,其他问题都没有这个答案。大多数人只是说这是一个错误,无法修复。要添加到您的答案中,可以将 navigationViewStyle 放在顶层:ContentView().navigationViewStyle(StackNavigationViewStyle()) 这修复了所有视图!
  • 几乎就在那里 - .navigationViewStyle(StackNavigationViewStyle()) 需要位于 NavigationView 闭包的末尾,而不是正文。否则就行了 - 非常感谢。
【解决方案2】:

NavigationBarTitle 已被 iOS 14.3 弃用。 但是,如果您仍想使用它,请尝试添加 .navigationViewStyle(StackNavigationViewStyle())navigationView 这将修复警告。

       struct ContentView: View {
        var body: some View {
            NavigationView {
                VStack {
                    Text("Hello, world!")
                        .padding()
                    Spacer()
                }
                .navigationBarTitle("Hey there", displayMode: .inline)
            }
            .navigationViewStyle(StackNavigationViewStyle())
        }
    }

新方式:

.navigationBarTitleDisplayMode(.inline)
.toolbar(content: {
     ToolbarItem(placement: .principal, content: {
     Text("Title")
  })})    

【讨论】:

  • navigationTitle 未被弃用。 developer.apple.com/documentation/swiftui/view/…
  • 它修复了警告,但如果它已弃用,那么新的解决方案是什么?
  • @Khodour.F 它没有被弃用
  • 某人如何使用new .navigationBarTitleDisplayMode(.large)!?我在哪里分配项目列表的标题!?
  • 如果你想在 iPad 上支持拆分视图,这不好。通过强制执行StackNavigationViewStyle 来解决问题并不是一个好的解决方案恕我直言。
【解决方案3】:

Xcode 13.0 Beta 1

除非您添加 StackNavigationViewStyle 修饰符,否则这仍然会导致约束错误。

但是,StackNavigationViewStyle 的文档指出:

不要直接使用这种类型。而是使用堆栈。

var body: some View {
    NavigationView {
        Text("Text")
            .navigationTitle("Title")
    }
    .navigationViewStyle(.stack)
}

【讨论】:

  • 这应该是正确答案
【解决方案4】:

iOS 14.3 已弃用 NavigationBarTitle https://developer.apple.com/documentation/swiftui/view/navigationbartitle(_:displaymode:)-8buvp

您可以使用 NavigationTitle.navigationViewStyle(StackNavigationViewStyle())

import SwiftUI

struct HomeView: View {
    var body: some View {
        NavigationView {
            Text("Text")
                .navigationBarTitle("Hey there", displayMode: .inline)
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
}

【讨论】:

  • 在使用 .navigationTitle(Text("Foo")).navigationBarTitleDisplayMode(.large) 修饰符时,我的日志中仍然出现约束错误。
  • @MartinBean 您可以在 Navigation 的子视图中使用 NavigationTitle。在 NavigationView 中,我建议您使用上述方法(带有 ToolbarItem 的工具栏)。
  • navigationBarTitle 已弃用,但 navigationTitle 未弃用。 developer.apple.com/documentation/swiftui/view/…。所以这些错误可能是 Xcode 版本中的错误
  • 如果你正在构建一个带有侧边栏导航的 iPad 应用程序,那么使用 StackNavigationViewStyle() 是不行的。此外,它似乎并没有使错误消失。
【解决方案5】:

以上所有的答案都不是很完整,所以我想补充一下,因为我研究了很长时间,这就是我的想法。我认为它会很有用:

Navigation View 的一个有趣之处在于它如何在大型设备(通常是 iPhone 和大型 iPad)上执行分屏功能。

var body: some View {
        NavigationView {
            Text("Primary")
        }
    }

如果你旋转到 iPhone 11 ProMax 的横向 (Cmd + ->),你会看到文本视图消失了。

SwiftUI 自动考虑横向导航视图并显示 DetailView 而不是 main(“Primary”)。

你可以通过在 NavigationView 中提供两个视图来解决问题,例如:

var body: some View {
        NavigationView {
            Text("Primary")
            Text("Secondary")
        }
    }

由于名气不大,所以只能发一张带链接的照片(如果我的帖子有用,请评价): enter image description here

这就是为什么如果我们添加. navigation Bar Title(Text ("Today's Flavors"), displayMode:. inline)会抛出错误“无法同时满足约束”

因此,解决方法如下:

  1. 向导航视图添加第二个视图

这里,当你旋转屏幕时,屏幕#2 - Text("Secondary") 将被显示出来。

    var body: some View {
            NavigationView {
                Text("Primary")
                Text("Secondary")
            .navigationBarTitle(Text("Today's Flavors"), displayMode: .inline)
            }
    }
  1. 修饰符.navigationViewStyle(StackNavigationViewStyle())

但是,如果您想明确指定旋转时始终显示第一个屏幕 (Text("Primary")),那么您需要添加 .navigationViewStyle(StackNavigationViewStyle) modifier()) ,它可以让您始终切换到 Text (" Primary"),无论屏幕如何。

var body: some View {
        NavigationView {
            Text("Primary")
            Text("Secondary")
        .navigationBarTitle(Text("Today's Flavors"), displayMode: .inline)
        }
        .navigationViewStyle(StackNavigationViewStyle())

此外,您还可以阅读有关 NavigationView 的更多信息here

【讨论】:

    【解决方案6】:

    我在使用这种方法时没有收到约束通知:

    import SwiftUI
    
    struct ConstraintIssue: View {
        var body: some View {
            NavigationView {
                Text("Detail View")
                    .toolbar(content: {
                        ToolbarItem(placement: .principal, content: {
                            Text("Detail View Title")
                        })
                        ToolbarItem(placement: .navigationBarTrailing, content: {
                          Button(action: {
                            print("Button Pressed")
                          }) {
                            Image(systemName: "ellipsis")
                          })
                       }
                    }
                )
            }
        }
    }
    

    【讨论】:

    • 不错!现在与我能说的唯一区别是,当您使用 .navigationTitle 而不是 ToolbarItem(placement: .principal.large .navigationBarTitleDisplayMode 时,您会得到很好的滚动行为,其中标题很大且左对齐,然后当您向下滚动时固定在导航栏中的中心并且更小,如果这有意义的话。基本上滚动的默认旧行为不同?
    【解决方案7】:
    struct QuizView: View {
        var body: some View {
    
            NavigationView{
                Text("Hello, world!")
                 .navigationBarTitle("Ripa", displayMode: .inline)
            }
            .navigationViewStyle(StackNavigationViewStyle()) /// add this line
    
        }
    }
    

    【讨论】:

    • 添加这行navigationViewStyle(StackNavigationViewStyle()) 即可解决问题
    【解决方案8】:

    今天用这个简单的视图更新到 Xcode 12.3 后,我也有这些警告,但它看起来很正常,没有错误。猜猜这是新 Xcode 版本的错误。

    struct ContentView: View {
        var body: some View {
            NavigationView {
                Text("Hello World")
                    .navigationTitle("Hello World")
                    .toolbar {
                        ToolbarItem(placement: .navigationBarLeading) {
                            Button(action: {},
                                label: {
                                Image(systemName: "plus.circle")
                            })
                        }
                        ToolbarItem(placement: .navigationBarTrailing) {
                            Button(action: {},
                                label: {
                                Image(systemName: "plus.circle")
                            })
                        }
                    }
            }
        }
    }
    

    这里是警告

    2020-12-16 14:25:05.897555+0800 TestingSwiftUI[76909:541649] [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. 
    (
        "<NSLayoutConstraint:0x600002847020 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x7f7f7fc19680]-(6)-[_UIModernBarButton:0x7f7f8200ff20'HelloWorld']   (active)>",
        "<NSLayoutConstraint:0x600002847070 'CB_Trailing_Trailing' _UIModernBarButton:0x7f7f8200ff20'HelloWorld'.trailing <= _UIButtonBarButton:0x7f7f7fc18740.trailing   (active)>",
        "<NSLayoutConstraint:0x600002847de0 'UINav_static_button_horiz_position' _UIModernBarButton:0x7f7f7fc19680.leading == UILayoutGuide:0x6000032689a0'UIViewLayoutMarginsGuide'.leading   (active)>",
        "<NSLayoutConstraint:0x600002847ed0 'UINavItemContentGuide-leading' H:[_UIButtonBarButton:0x7f7f7fc18740]-(0)-[UILayoutGuide:0x6000032688c0'UINavigationBarItemContentLayoutGuide']   (active)>",
        "<NSLayoutConstraint:0x60000286a440 'UINavItemContentGuide-trailing' UILayoutGuide:0x6000032688c0'UINavigationBarItemContentLayoutGuide'.trailing == _UINavigationBarContentView:0x7f7f8200e2c0.trailing   (active)>",
        "<NSLayoutConstraint:0x60000285c410 'UIView-Encapsulated-Layout-Width' _UINavigationBarContentView:0x7f7f8200e2c0.width == 0   (active)>",
        "<NSLayoutConstraint:0x60000286a800 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x6000032689a0'UIViewLayoutMarginsGuide'](LTR)   (active, names: '|':_UINavigationBarContentView:0x7f7f8200e2c0 )>"
    )
    
    Will attempt to recover by breaking constraint 
    <NSLayoutConstraint:0x600002847020 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x7f7f7fc19680]-(6)-[_UIModernBarButton:0x7f7f8200ff20'HelloWorld']   (active)>
    
    Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
    The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
    

    当我删除时

    .navigationTitle("Hello World")
    

    警告消失了

    所以我要向 Apple 报告这个问题

    this view looks normal

    【讨论】:

    • 我也看到了这个,但奇怪的是,当我在根页面上使用 .navigationTitle 时,我仍然收到错误,(但看起来不错)但如果我在子视图中使用它(导航链接-ed 查看)我没有收到错误消息。
    【解决方案9】:

    我总是收到相同的警告,但一切正常。现在就像你说的,我删除了 .navigationtTitle(),警告消失了,它看起来像一个错误。

    【讨论】:

      【解决方案10】:

      我认为这是 Xcode 新版本的 BUG。 以前的版本没有这个错误。

      【讨论】:

      • 这不是错误,只是已弃用。
      【解决方案11】:

      只需将 .navigationBarTitle("string") 替换为 .navigationTitle("string") 即可。 并添加 .navigationViewStyle。

      【讨论】:

        【解决方案12】:

        很遗憾,如果您正在构建一个使用侧边栏的 iPad 应用程序,那么许多建议使用 StackNavigationViewStyle() 的解决方案都将不起作用。

        如果添加这一行,再深入一点:

        UserDefaults.standard.set(false, forKey: "_UIConstraintBasedLayoutLogUnsatisfiable")
        

        在您的 AppDelegateApp 实例中将抑制错误。您将收到一条警告,说明您已禁用它。我相信这是可以接受的,因为通过使用 SwiftUI,我们不必担心 LayoutConstraints,并且希望 Apple 在默认情况下抑制这些东西,因为我们使用的是 SwiftUI。

        see this SO answer for more info

        【讨论】:

          【解决方案13】:

          一个小笔记.. 我错了还是ADC代码错了??

          你可以阅读:

          .navigationBarTitle(Text("Today's Flavors", displayMode: .inline)
          

          但是错了: “无法根据成员 'inline' 推断上下文基础”

          他们放错了括号:

          正确的代码是:

          .navigationBarTitle(Text("Today's Flavors"), displayMode: .inline)
          

          如果您想尝试,请完成代码...

          import SwiftUI
          
          
          struct ContentView: View {
              let items = ["Chocolate", "Vanilla", "Strawberry", "Mint Chip",
                              "Pistachio"]
                 var body: some View {
                      NavigationView {
                           List(items, id: \.self) {
                               Text($0)
                           }
                          .navigationBarTitle(Text("Today's Flavors"), displayMode: .inline)
                      }
                  }
          }
          
          struct ContentView_Previews: PreviewProvider {
              static var previews: some View {
                  ContentView()
              }
          }
          

          PS

          2021 年 3 月,Apple 已修复.. 但您可以尝试使用假代码复制... 例如这里:

          https://gist.github.com/erica/6941e2adfce75807bcd64550b3669c26

          【讨论】:

            猜你喜欢
            • 2020-12-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-08-05
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多