SwiftUI NavigationView navigationBarTitle LayoutConstraints issue
IosSwiftSwiftuiIos Problem Overview
This is maybe related to the new (12.3) version of XCode that came out recently but I have a very simple SwiftUI View:
import SwiftUI
struct HomeView: View {
var body: some View {
NavigationView {
Text("Text")
.navigationBarTitle("My Title")
}
}
}
And I'm getting this warning in the console:
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.
This simple example looks fine but when I do something a bit more complex:
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")
}
)
}
}
}
The Navigation Title areas layout is all screwed up:
Ios Solutions
Solution 1 - Ios
It had nothing to do with NavigationBarTitle
. .navigationTitle
is not deprecated. Seems whole issue is mainly with new Xcode 12.4 update, even for simple code:
var body: some View {
NavigationView{
Text("Hopefully will work this time")
.navigationTitle("Error with constains")
}
}
adding .navigationViewStyle(StackNavigationViewStyle())
fixes problem
var body: some View {
NavigationView{
Text("Yes it does!")
.navigationTitle("Wow it works")
}
}.navigationViewStyle(StackNavigationViewStyle())
PS. My first stackoverflow reply xD
Solution 2 - Ios
NavigationBarTitle
is deprecated from iOS 14.3
.
However if you still wish to use it, try to add
.navigationViewStyle(StackNavigationViewStyle())
on the navigationView
that will fix the warning.
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Text("Hello, world!")
.padding()
Spacer()
}
.navigationBarTitle("Hey there", displayMode: .inline)
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
The new way:
.navigationBarTitleDisplayMode(.inline)
.toolbar(content: {
ToolbarItem(placement: .principal, content: {
Text("Title")
})})
Solution 3 - Ios
Xcode 13.0 Beta 1
This is still causing a contraint error unless you add the StackNavigationViewStyle modifier.
However, the documentation for StackNavigationViewStyle
states:
Do not use this type directly. Instead, use stack.
var body: some View {
NavigationView {
Text("Text")
.navigationTitle("Title")
}
.navigationViewStyle(.stack)
}
Solution 4 - Ios
NavigationBarTitle is deprecated from iOS 14.3 https://developer.apple.com/documentation/swiftui/view/navigationbartitle(_:displaymode:)-8buvp
You can use NavigationTitle and .navigationViewStyle(StackNavigationViewStyle())
import SwiftUI
struct HomeView: View {
var body: some View {
NavigationView {
Text("Text")
.navigationBarTitle("Hey there", displayMode: .inline)
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
Solution 5 - Ios
All of the above answers are not quite complete, so I would like to add, because I have studied this question for a long time and this is what I came to. I think it will be useful:
One of the interesting things about Navigation View is how it also performs the split-screen function on large devices-usually iPhones and large iPads.
var body: some View {
NavigationView {
Text("Primary")
}
}
If you rotate to landscape orientation (Cmd + ->) of the iPhone 11 ProMax, you will see that the text view disappears.
SwiftUI automatically considers landscape navigation views and shows DetailView instead of main ("Primary").
You can solve the problem the way SwiftUI expects by providing two views inside your NavigationView, for instance:
var body: some View {
NavigationView {
Text("Primary")
Text("Secondary")
}
}
Since I have little reputation, I can only post a photo with a link (If my post was useful, please rate it): enter image description here
This is why the error "Unable to simultaneously satisfy constraints" is thrown if we add. navigation Bar Title(Text ("Today's Flavors"), displayMode:. inline)
Therefore, the solution is as follows:
- Add a second view to the Navigation View
Here, when you rotate the screen, screen # 2 - Text("Secondary") will be displayed.
var body: some View {
NavigationView {
Text("Primary")
Text("Secondary")
.navigationBarTitle(Text("Today's Flavors"), displayMode: .inline)
}
}
2) Modifier .navigationViewStyle(StackNavigationViewStyle())
However, if you want to explicitly specify that the first screen (Text("Primary")) is always displayed when you rotate, then you need to add the .navigationViewStyle(StackNavigationViewStyle) modifier())
, which allows you to always switch to Text ("Primary"), regardless of the screen.
var body: some View {
NavigationView {
Text("Primary")
Text("Secondary")
.navigationBarTitle(Text("Today's Flavors"), displayMode: .inline)
}
.navigationViewStyle(StackNavigationViewStyle())
Also, you can read, more about NavigationView here
Solution 6 - Ios
struct QuizView: View {
var body: some View {
NavigationView{
Text("Hello, world!")
.navigationBarTitle("Ripa", displayMode: .inline)
}
.navigationViewStyle(StackNavigationViewStyle()) /// add this line
}
}
Solution 7 - Ios
I don't get the constraint notice when using this approach:
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")
})
}
}
)
}
}
}
Solution 8 - Ios
Unfortunately, a lot of the solutions advising the use of StackNavigationViewStyle()
won't work if you're building an iPad app which uses the sidebar.
Digging a little deeper, if you add this line:
UserDefaults.standard.set(false, forKey: "_UIConstraintBasedLayoutLogUnsatisfiable")
in either your AppDelegate
or App
instance will suppress the errors. You'll get a one line warning that you've disabled it. I believe this is acceptable, since by using SwiftUI we shouldn't have to worry about LayoutConstraints and hopefully Apple will suppress this stuff by default since we're using SwiftUI.
Solution 9 - Ios
I also have these warnings after updating to Xcode 12.3 today with this simple view but it looks normal with no bugs. guess that is a bug of new Xcode version.
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")
})
}
}
}
}
}
Here are the warnings
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.
when I delete
.navigationTitle("Hello World")
the warnings disappeared
so I'm gonna report this issue to Apple
Solution 10 - Ios
I got the same warnings always, but everything works fine. Now like you said, I delete the .navigationtTitle(), and the warnings disappears, it looks like a bug .
Solution 11 - Ios
Just replace the .navigationBarTitle("string") with .navigationTitle("string") is fine. And add .navigationViewStyle.
Solution 12 - Ios
a small note.. I am wrong or ADC code is wrong??
You can read:
.navigationBarTitle(Text("Today's Flavors", displayMode: .inline)
BUT is wrong: “Cannot infer contextual base in reference to member 'inline’”
They mis-placed a parenthesis:
Right code is:
.navigationBarTitle(Text("Today's Flavors"), displayMode: .inline)
complete code if You want to try...
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
in MARCH 2021 Apple has fixed.. but you can try copies around with fake code... for example here:
https://gist.github.com/erica/6941e2adfce75807bcd64550b3669c26