SwiftUI NavigationView navigationBarTitle LayoutConstraints 问题

god*_*yan 53 ios swift swiftui

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

import SwiftUI

struct HomeView: View {
    var body: some View {
        NavigationView {
            Text("Text")
                .navigationBarTitle("My Title")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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.
Run Code Online (Sandbox Code Playgroud)

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

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")
                }
            )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

在此处输入图片说明

rba*_*win 62

Xcode 13.0 测试版 1

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

但是,文档说明StackNavigationViewStyle

不要直接使用该类型。相反,使用堆栈。

var body: some View {
    NavigationView {
        Text("Text")
            .navigationTitle("Title")
    }
    .navigationViewStyle(.stack)
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是正确的答案 (7认同)

Hez*_*Ziv 39

NavigationBarTitleiOS 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())
        }
    }
Run Code Online (Sandbox Code Playgroud)

新方式:

.navigationBarTitleDisplayMode(.inline)
.toolbar(content: {
     ToolbarItem(placement: .principal, content: {
     Text("Title")
  })})    
Run Code Online (Sandbox Code Playgroud)

  • navigationTitle 并未被弃用。https://developer.apple.com/documentation/swiftui/view/navigationtitle(_:)-43srq (8认同)
  • 如果你想在 iPad 上支持分割视图,这不太好。恕我直言,通过强制执行“StackNavigationViewStyle”来解决问题并不是一个好的解决方案。 (2认同)

小智 30

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

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

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

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

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

  • 兄弟,这就是答案!我已经搜索这个问题几个星期了,其他问题都没有这个答案。大多数人只是说这是一个错误并且无法修复。要添加到您的答案中,可以将 navigationViewStyle 放置在顶层: `ContentView().navigationViewStyle(StackNavigationViewStyle())` 这修复了所有视图! (7认同)
  • 这更优雅一点 - ```.navigationViewStyle(.stack)``` (6认同)
  • 几乎就在那里 - .navigationViewStyle(StackNavigationViewStyle()) 需要位于 NavigationView 闭包的末尾,而不是主体。否则就可以了——非常感谢。 (3认同)

Eld*_*dar 13

上面的答案都不太完整,所以我想补充一下,因为我研究了这个问题很长时间,这就是我得出的结论。我认为这会很有用:

导航视图的有趣之处之一是它如何在大型设备(通常是 iPhone 和大型 iPad)上执行分屏功能。

var body: some View {
        NavigationView {
            Text("Primary")
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

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

您可以通过在 NavigationView 中提供两个视图来按照 SwiftUI 期望的方式解决问题,例如:

var body: some View {
        NavigationView {
            Text("Primary")
            Text("Secondary")
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

这就是为什么如果我们添加,会抛出错误“无法同时满足约束”. 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)
            }
    }
Run Code Online (Sandbox Code Playgroud)
  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())
Run Code Online (Sandbox Code Playgroud)

另外,您可以在此处阅读有关 NavigationView 的更多信息


Thi*_*ang 11

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())
    }
}
Run Code Online (Sandbox Code Playgroud)

  • navigationBarTitle 已弃用,但 navigationTitle 并未弃用。https://developer.apple.com/documentation/swiftui/view/navigationtitle(_:)-5di1u。所以这些错误可能是 Xcode 版本中的错误 (6认同)
  • 使用 `.navigationTitle(Text("Foo"))` 和 `.navigationBarTitleDisplayMode(.large)` 修饰符时,我的日志中仍然出现约束错误。 (2认同)

Ami*_*kur 10

struct QuizView: View {
    var body: some View {

        NavigationView{
            Text("Hello, world!")
             .navigationBarTitle("Ripa", displayMode: .inline)
        }
        .navigationViewStyle(StackNavigationViewStyle()) /// add this line

    }
}
Run Code Online (Sandbox Code Playgroud)

  • 添加这一行 navigationViewStyle(StackNavigationViewStyle()) 将解决问题 (2认同)

lor*_*sum 5

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

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")
                      })
                   }
                }
            )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)