I have begun getting an error message in my console whenever I have a NavigationView nested inside a TabView, I am getting the below error. Is there a fix for this?
struct ContentView: View {
var body: some View {
TabView{
NavigationView{
Text("Hello, world!")
.padding()
.navigationBarTitle("Hello World")
}
.tag(0)
.tabItem {
Text("Main")
}
NavigationView{
Text("Hello, world!")
.padding()
}
.tag(1)
.tabItem {
Text("Secondary")
}
}.edgesIgnoringSafeArea(.top)
}
}
My console spits out the below error:
2021-03-26 14:14:59.294828-0600 Playground[39119:2828740] [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:0x600001ae5fe0 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x7fdded4274f0]-(6)-[_UIModernBarButton:0x7fdded428920'Hello World'] (active)>",
"<NSLayoutConstraint:0x600001ae6030 'CB_Trailing_Trailing' _UIModernBarButton:0x7fdded428920'Hello World'.trailing <= _UIButtonBarButton:0x7fdded7079f0.trailing (active)>",
"<NSLayoutConstraint:0x600001ae0230 'UINav_static_button_horiz_position' _UIModernBarButton:0x7fdded4274f0.leading == UILayoutGuide:0x6000000df1e0'UIViewLayoutMarginsGuide'.leading (active)>",
"<NSLayoutConstraint:0x600001ae94f0 'UINavItemContentGuide-leading' H:[_UIButtonBarButton:0x7fdded7079f0]-(0)-[UILayoutGuide:0x6000000df100'UINavigationBarItemContentLayoutGuide'] (active)>",
"<NSLayoutConstraint:0x600001aee800 'UINavItemContentGuide-trailing' UILayoutGuide:0x6000000df100'UINavigationBarItemContentLayoutGuide'.trailing == _UINavigationBarContentView:0x7fdded4253a0.trailing (active)>",
"<NSLayoutConstraint:0x600001ae9cc0 'UIView-Encapsulated-Layout-Width' _UINavigationBarContentView:0x7fdded4253a0.width == 0 (active)>",
"<NSLayoutConstraint:0x600001aeebc0 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x6000000df1e0'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':_UINavigationBarContentView:0x7fdded4253a0 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600001ae5fe0 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x7fdded4274f0]-(6)-[_UIModernBarButton:0x7fdded428920'Hello World'] (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.
I found the answer here:
SwiftUI NavigationView navigationBarTitle LayoutConstraints issue
I needed to add .navigationViewStyle(StackNavigationViewStyle())
When I updated the code to this, the error went away:
struct ContentView: View {
var body: some View {
TabView{
NavigationView{
Text("Hello, world!")
.padding()
.navigationTitle("Hello World")
}
.navigationViewStyle(StackNavigationViewStyle())
.tag(0)
.tabItem {
Text("Main")
}
NavigationView{
Text("Hello, world!")
.padding()
}
.tag(1)
.tabItem {
Text("Secondary")
}
}.edgesIgnoringSafeArea(.top)
}
}
Related
Does anyone know how I can create a bottom sheet similar to the one in the Diary Queen app. I have tried a few times but every thing I've tried has made the bottom sheet appear above the bottom tabview. I need it to appear from behind the tabview just like in the screenshots.
I've tried a zstack, but every time my bottom view appears above.
import SwiftUI
struct Menu: View {
#State private var showingBottomSheet = true
var body: some View {
TabView{
orderView()
.tabItem{
Image(systemName: "questionmark")
Text("Order")
}
rewardView()
.tabItem{
Image(systemName: "star")
Text("Rewards")
}
dealsView()
.tabItem{
Image(systemName: "tag")
Text("Deals")
}
myDQView()
.tabItem{
Image(systemName: "person")
Text("My DQ")
}
currentOrderView()
.tabItem{
Image(systemName: "bag")
}
}
.padding()
.sheet(isPresented: $showingBottomSheet) {
Text("hello")
//
}
}
}
struct Menu_Previews: PreviewProvider {
static var previews: some View {
Menu()
}
}
The solution to this, is to not use a .sheet, instead you need to have a view that is built and .offset(y:...) off the screen, and have it watch for your boolean value to change. For example:
struct Menu: View {
#State private var showingBottomSheet = false
var body: some View {
TabView{
Group {
ScrollView{}
.tabItem{
Image(systemName: "questionmark")
Text("Order")
}
Text("")
.tabItem{
Image(systemName: "star")
Text("Rewards")
}
Text("")
.tabItem{
Image(systemName: "tag")
Text("Deals")
}
Text("")
.tabItem{
Image(systemName: "person")
Text("My DQ")
}
Text("")
.tabItem{
Image(systemName: "bag")
}
}
.background(
Color.gray.offset(y: showingBottomSheet ? 0 : UIScreen.main.bounds.size.height - 120)
)
}
}
}
Notice that constructing it like this, puts it behind your view. Also in this example, I set the height - 120 soley so if you copied this, you'll see that the offset is indeed behind the other view. I was also forced to use a ScrollView and replace all the other views with Text because you didn't post those views, the principle should still remain the same.
In the order view, create #state variable and using if statement to display the custom view as a sheet
struct Order: View {
#State var isShow: Bool = true
var body: some View {
ZStack(alignment: .bottom) {
VStack {
Button("Display Sheet") {
isShow.toggle()
}
Spacer()
}
if isShow {
RoundedRectangle(cornerRadius: 20)
.fill(Color.gray.opacity(0.2))
.frame(height: UIScreen.main.bounds.height * 0.8)
.transition(.push(from: .bottom))
.animation(.easeInOut(duration: 1))
}
}
}
}
The code below changes the selection variable. Why? I thought a custom handler allowed me to intercept everything. The behavior I expect is for nothing to happen when I press a tab item. But what it does is set the selection variable and change the view. What gives?
struct ContentView: View {
#State private var selection = 0
var handler: Binding<Int> { Binding(
get: { selection },
set: { log.info("I don't set the selection variable, the tab changes \($0)") }
) }
var body: some View {
ZStack {
TabView(selection: handler) {
Text("view 0")
.tabItem {
Label("Home", systemImage: "house.fill")
}.tag(0)
Text("view 1")
.tabItem {
Label("Arrows", systemImage: "arrow.left.arrow.right")
}.tag(1)
Text("view 3")
.tabItem {
Label("Arrow Up", systemImage: "arrow.up")
}.tag(2)
}
}
}
}
I'm having an issue with Xcode throwing a constraint message in the console every time I use a NavigationTitle.
I'd like to say that I've read through the following post and have tried adding StackedNavigationViewStyle(). This worked for iOS 14 and Xcode 12.3. Since upgrading to iOS 15 and Xcode 13 the solution stops working.
SwiftUI NavigationView navigationBarTitle LayoutConstraints issue
The message is.
[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:0x28189d540 UIView:0x155f53c50.trailing == _UIBackButtonMaskView:0x155f538f0.trailing (active)>",
"<NSLayoutConstraint:0x281890af0 'Mask_Trailing_Trailing' _UIBackButtonMaskView:0x155f538f0.trailing == _UIButtonBarButton:0x155f52d00.trailing (active)>",
"<NSLayoutConstraint:0x2818912c0 'MaskEV_Leading_BIB_Trailing' H:[_UIModernBarButton:0x155f53610]-(0)-[UIView:0x155f53c50]
(active)>",
"<NSLayoutConstraint:0x281890c30 'UINav_static_button_horiz_position'
_UIModernBarButton:0x155f53610.leading == UILayoutGuide:0x2802a5ce0'UIViewLayoutMarginsGuide'.leading
(active)>",
"<NSLayoutConstraint:0x281890640 'UINavItemContentGuide-leading' H:[_UIButtonBarButton:0x155f52d00]-(6)-[UILayoutGuide:0x2802a5dc0'UINavigationBarItemContentLayoutGuide']
(active)>",
"<NSLayoutConstraint:0x28189dd60 'UINavItemContentGuide-trailing' UILayoutGuide:0x2802a5dc0'UINavigationBarItemContentLayoutGuide'.trailing
== _UINavigationBarContentView:0x155f51f30.trailing (active)>",
"<NSLayoutConstraint:0x28189b340 'UIView-Encapsulated-Layout-Width'
_UINavigationBarContentView:0x155f51f30.width == 0 (active)>",
"<NSLayoutConstraint:0x28189e300 'UIView-leftMargin-guide-constraint'
H:|-(8)-UILayoutGuide:0x2802a5ce0'UIViewLayoutMarginsGuide'
(active, names: '|':_UINavigationBarContentView:0x155f51f30 )>" )
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x28189d540 UIView:0x155f53c50.trailing ==
_UIBackButtonMaskView:0x155f538f0.trailing (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 adding StackedNavigationViewStyle to an iOS 15 app the Title and TabBar become inactive and the list moves underneath.
The code for this is below.
struct Tab1: View {
var body: some View {
// // Used for PacificBlue color.
UITableView.appearance().backgroundColor = .clear
// UITableView.appearance().separatorColor = UIColor(Color.white)
return NavigationView {
ZStack {
Color.pacificBlue
.edgesIgnoringSafeArea(.all)
List {
ForEach(1..<100) { index in
if #available(iOS 15.0, *) {
NavigationLink(destination: DetailView()) {
HStack {
Text("Row \(index)")
//
.listRowSeparatorTint(Color.pink)
}
.background(Color.pacificBlue)
} // NavigationLink
.listRowSeparatorTint(Color.pink)
} else {
// Fallback on earlier versions
NavigationLink(destination: DetailView()) {
Text("Row \(index)")
} // NavigationLink
} // if else
} // ForEach
.listRowBackground(Color.pacificBlue)
} // List
.listStyle(PlainListStyle())
} // ZStack
.navigationTitle("Title")
} // NavigationView
.navigationViewStyle(StackNavigationViewStyle())
} // View
}
If built on iOS 14 the expected behavior is seen.
Any help would be appreciated.
Recently, I was challenged by the same issue of NavigationBar and TabBar becoming transparent and unresponsive to scroll with IOS 15.0 exclusively, while IOS 14 and IOS 15.2 and above had normal behavior. After many hours of identifying the problem, I discovered that it caused by combination of .navigationViewStyle(.stack) and the ZStack that's used inside to provide Color as background. I have no explanation why it behaves like that, neither why the solutions work.
Option 1: Wrap the NavigationView with another ZStack
struct ContentView: View {
var body: some View {
UITableView.appearance().backgroundColor = .clear
return ZStack {
NavigationView {
ZStack {
Color.blue
.edgesIgnoringSafeArea(.all)
List {
ForEach(1...50, id:\.self) { index in
Text("Row \(index)")
}
}
}
.navigationTitle("Title")
}
.navigationViewStyle(.stack)
}
}
}
Option 2: Apply the ZStack only to IOS 15 with a ViewModifier
struct ContentView: View {
var body: some View {
UITableView.appearance().backgroundColor = .clear
return NavigationView {
ZStack {
Color.blue
.edgesIgnoringSafeArea(.all)
List {
ForEach(1...50, id:\.self) { index in
Text("Row \(index)")
}
}
}
.navigationTitle("Title")
}
.navigationViewStyle(.stack)
.modifier(NavigationModifier())
}
}
struct NavigationModifier: ViewModifier {
func body(content: Content) -> some View {
if #available(iOS 15.0, *) {
ZStack {
content
}
} else {
content
}
}
}
I had the same problem using NavigationView and TabView together. Until iOS 14 I used the code bellow and it worked without problem:
NavigationView{
TabView(selection: $selection) {
...
}
}
However, since iOS 15, the same code started having the same navigationTitle you're having.
After a lot of time searching for a solution I found that if we change the order it works perfectly:
struct ContentView: View {
var body: some View {
TabView(selection: $selection) {
NavigationView {
Text("Example 1")
.navigationTitle("One")
}
.tabItem {
Text("One")
}
.tag("One")
NavigationView {
Text("Example 2")
.navigationTitle("Two")
}
.tabItem {
Text("Two")
}
.tag("Two")
}
}
}
I am having trouble with a return from a navigation view within a tabbed view. My project has a Settings tab where the user may select via navigation link "View Entries". And from there another navigation link to "Add New Entry". Returning from Add New Entry should bring you to View Entries but instead is return another level to the Setting Menu.
I am seeing a warning on the console stating "trying to pop to a missing destination at /Library/Caches/com.apple...". Using the tabbed view sample code at SwiftUI NavigationView trying to pop to missing destination (Monoceros?) I no longer get the "pop-to-missing-destination" warning but I still have the same problem with the navigation return.
The sample code below is ready to run and test in Xcode 12.
In the sample code below, tap settings and select the navigation view "View Entries". This would be a screen where entries are displayed in a list. Tapping the plus button is where new entries could be added. The textfield on the "Add New Entry" screen doesn't do anything. Clicking the Save or Back buttons should return you to "View Entries" screen but instead returns you to the Setting Menu. The Save button uses presentationMode.wrappedValue.dismiss to dismiss the view.
The fact that two different version of the tab view logic didn't have any impact on my navigation view return logic leads me to believe that I just have some kind on plain old bug in my navigation view logic but I sure don't see one. The sample code below is using the standard tab view logic.
struct ContentView: View {
#State private var selection = 0
var body: some View {
NavigationView {
TabView (selection: $selection) {
HomeView()
.tabItem {
Label("Home", systemImage: "house")
}.tag(1)
AView()
.tabItem {
Label("A", systemImage: "a.circle")
}.tag(2)
BView()
.tabItem {
Label("B", systemImage: "b.circle")
}.tag(3)
SettingsView()
.tabItem {
Label("Settings", systemImage: "gearshape")
}.tag(4)
}
}
}
}
struct HomeView: View {
var body: some View {
Text("Home Screen")
}
}
struct AView: View {
var body: some View {
Text("A Screen")
}
}
struct BView: View {
var body: some View {
Text("B Screen")
}
}
struct SettingsView: View {
var body: some View {
VStack (alignment: .leading) {
List {
Text("Settings")
.font(.title)
.fontWeight(.bold)
.padding(.leading, 15)
NavigationLink(destination: SetAView()) {Text("View Entries")}
}
}
.font(.body)
}
}
struct SetAView: View {
var body: some View {
List {
Text("View Entries")
.padding(.vertical, 10)
Text("Normally entires would be displayed here")
Text("Should return here upon adding new entry")
.padding(.vertical, 10)
Text("Click the + button to add new entry")
}
.navigationBarItems(trailing: NavigationLink (destination: AddTestView()) {
Image(systemName: "plus")
.resizable()
.foregroundColor(Color(.systemBlue))
.frame(width: 18, height: 18)
} // body
)
}
}
struct AddTestView: View {
#Environment(\.presentationMode) var presentationMode
#State private var catSelect: String = ""
var body: some View {
NavigationView {
VStack {
Form {
Section {
TextField("Enter Entry Name", text: $catSelect)
.padding(.horizontal, 20)
.keyboardType(.default)
}
}
}
.navigationBarTitle(Text("Add new Entry"), displayMode: .inline)
.navigationViewStyle(StackNavigationViewStyle())
.navigationBarItems(trailing: Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text ("Save")
})
}
}
}
After considerable analysis I discovered in my actual code that I had two copies of NavigationView––nothing wrong with the TabView code. Removing the one NavigationView not in contentView then caused several functions from working so rebuilt them from scratch. Now have everything working with TabView and NaigationView including the back buttons.
Environment: Xcode Version 12.3 (12C33)
Version 12.3 (12C33)
I notice that the NavigationTitle breaks the autolayout after updating to Xcode 12.3 RC.
Here's a simple example (revised to modern syntax per comment):
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
VStack(alignment: .center, spacing: 10) {
Text("Hello, world!")
.padding()
}.navigationTitle(Text("Greetings World!"))
.navigationBarTitleDisplayMode(.inline)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Here's what I get upon running this:
2020-12-09 11:42:19.994389-0800 UICheck[26092:799713] [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:0x60000170e1c0 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x7feb5ac096e0]-(6)-[_UIModernBarButton:0x7feb5ac06db0'Greetings World!'] (active)>",
"<NSLayoutConstraint:0x60000170e210 'CB_Trailing_Trailing' _UIModernBarButton:0x7feb5ac06db0'Greetings World!'.trailing <= _UIButtonBarButton:0x7feb5ac066a0.trailing (active)>",
"<NSLayoutConstraint:0x60000170ef80 'UINav_static_button_horiz_position' _UIModernBarButton:0x7feb5ac096e0.leading == UILayoutGuide:0x600000d5db20'UIViewLayoutMarginsGuide'.leading (active)>",
"<NSLayoutConstraint:0x60000170efd0 'UINavItemContentGuide-leading' H:[_UIButtonBarButton:0x7feb5ac066a0]-(0)-[UILayoutGuide:0x600000d5da40'UINavigationBarItemContentLayoutGuide'] (active)>",
"<NSLayoutConstraint:0x60000170ae90 'UINavItemContentGuide-trailing' UILayoutGuide:0x600000d5da40'UINavigationBarItemContentLayoutGuide'.trailing == _UINavigationBarContentView:0x7feb5ae185f0.trailing (active)>",
"<NSLayoutConstraint:0x60000170f750 'UIView-Encapsulated-Layout-Width' _UINavigationBarContentView:0x7feb5ae185f0.width == 0 (active)>",
"<NSLayoutConstraint:0x60000170b250 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x600000d5db20'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':_UINavigationBarContentView:0x7feb5ae185f0 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x60000170e1c0 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x7feb5ac096e0]-(6)-[_UIModernBarButton:0x7feb5ac06db0'Greetings World!'] (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 is the source of the problem:
I suspect this to be another Apple Bug.
Being that I'm using the supplied .navigationBarTitle view, how can I fix this?
Updated for Xcode 13
To solve the LayoutConstraints error on SwiftUI NavigationView, make it conform to this style:
.navigationViewStyle(StackNavigationViewStyle()) on Xcode 12
.navigationViewStyle(.stack) on Xcode 13
struct ContentView: View {
var body: some View {
NavigationView {
VStack(alignment: .center, spacing: 10) {
Text("Hello world!")
.padding()
}
.navigationTitle("Greetings World!")
.navigationBarTitleDisplayMode(.inline)
}
.navigationViewStyle(.stack)
}
}