I cannot navigate deeper into the views in Swiftui - swift

I have three views in my project - ContentView, SecondView, ThirdView
I want to navigate from contentView to secondView and secondView to thirdView.
ContentView :-
import SwiftUI
struct ContentView: View {
#State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
Button {
path.append("SecondView")
} label: {
Text("This is the first view")
}
.navigationDestination(for: String.self) { view2 in
if view2 == "SecondView" {
SecondView()
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
SecondView :-
import SwiftUI
struct SecondView: View {
#State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
Button {
path.append("ThirdView")
} label: {
Text("This is the second view")
}
.navigationDestination(for: String.self) { view2 in
if view2 == "ThirdView" {
ThirdView()
}
}
}
}
}
struct SecondView_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {
SecondView()
}
}
}
ThirdView :-
import SwiftUI
struct ThirdView: View {
var body: some View {
Text("This is the third view")
}
}
struct ThirdView_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {
ThirdView()
}
}
}
What is happening :-
Whenever I tap on the "This is the first view" button in my ContentView, I am navigated to SecondView and automatically navigated back to contentView.
What I want :-
I want to navigate from contentView to secondView and secondView to thirdView.

You shouldn't have multiple NavigationStacks in the hierarchy. You should have one and pass the path via a Binding.
struct ContentView: View {
#State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
Button {
path.append("SecondView")
} label: {
Text("This is the first view")
}
.navigationDestination(for: String.self) { view in
switch view {
case "SecondView":
SecondView(path: $path)
case "ThirdView":
ThirdView()
default:
Text("Unknown")
}
}
}
}
}
struct SecondView: View {
#Binding var path: NavigationPath
var body: some View {
Button {
path.append("ThirdView")
} label: {
Text("This is the second view")
}
}
}
struct ThirdView: View {
var body: some View {
Text("This is the third view")
}
}
struct SecondView_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {
SecondView(path: .constant(NavigationPath()))
}
}
}

Related

ConfirmationDialog cancel bug in swiftui

When I jump to the settings page and click Cancel in the pop-up dialog box, it will automatically return to the home page. How can I avoid this problem?
import SwiftUI
struct ContentView: View {
#State private var settingActive: Bool = false
var body: some View {
NavigationView {
TabView {
VStack {
NavigationLink(destination: SettingView(), isActive: $settingActive) {
EmptyView()
}
Button {
settingActive.toggle()
} label: {
Text("Setting")
}
}
.padding()
}
}
}
}
struct SettingView: View {
#State private var logoutActive: Bool = false
var body: some View {
VStack {
Button {
logoutActive.toggle()
} label: {
Text("Logout")
}
.confirmationDialog("Logout", isPresented: $logoutActive) {
Button("Logout", role: .destructive) {
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
This seems to be an issue with using TabView inside NavigationView.
You can solve this by moving TabView to be your top level object (where it really should be), or replacing NavigationView with the new NavigationStack.
Here's an implementation that also removes the deprecated NavigationLink method:
enum Router {
case settings
}
struct ContentView: View {
#State private var path = NavigationPath()
var body: some View {
TabView {
NavigationStack(path: $path) {
VStack {
Button {
path.append(Router.settings)
} label: {
Text("Setting")
}
}
.navigationDestination(for: Router.self) { router in
switch router {
case .settings:
SettingView(path: $path)
}
}
.padding()
}
}
}
}
struct SettingView: View {
#Binding var path: NavigationPath
#State private var logoutActive: Bool = false
var body: some View {
VStack {
Button {
logoutActive = true
} label: {
Text("Logout")
}
.confirmationDialog("Logout", isPresented: $logoutActive) {
Button("Logout", role: .destructive) {
}
}
}
}
}

Dismiss Presentation View - SWIFTUI

I am trying to build a app. I am using presentation mode to show the view, then I switch to another but when I use the dismiss function it just takes me back to the first view.
struct ContentView: View {
#Environment(\.presentationMode) var presentationMode
#State private var isShowingBookingScreen:Bool = false
var body: some View {
Button {
isShowingBookingScreen = true
} label: {
Spacer()
Text("Book Now").foregroundColor(.white).padding().font(.headline)
Spacer()
}.sheet(isPresented: $isShowingBookingScreen) {
SecondView()
}.background(Color.accentColor).cornerRadius(10).padding()
}
}
struct SecondView: View {
var body: some View {
NavigationView{
NavigationLink(destination:ThirdView()) {
Text("Continue to Third").foregroundColor(.red).padding().cornerRadius(10).padding()
}
}
}
}
struct ThirdView: View {
#Environment(\.presentationMode) var presentationMode
var body: some View {
Button {
presentationMode.wrappedValue.dismiss()
} label: {
Text("Dismiss")
}
}
}

How to pass data between SwiftUI views using NavigationLink

I am engaging in a small SwiftUI exercise to learn how to pass data between views using NavigationLink. I set up ContentView to send a message to the SecondView after tapping the ContentView NavigationLink. Tapping NavigationLink in the SecondView then sends the message to the ThirdView. However, I am noticing a strange UI occurrence by the time I get to ThirdView. See the screenshot below:
Any idea why this NavigationView issue is occurring? Is it related to having NavigationView in all 3 views?
Here is my code:
ContentView
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: SecondView(message: "Hello from ContentView")) {
Text("Go to Second View")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
SecondView
struct SecondView: View {
var message: String
var body: some View {
Text("\(message)")
NavigationView {
NavigationLink(destination: ThirdView(message: self.message)) {
Text("Go to Third View")
}
}
}
}
struct SecondView_Previews: PreviewProvider {
static var previews: some View {
SecondView(message: String())
}
}
ThirdView
struct ThirdView: View {
var message: String
var body: some View {
NavigationView {
Text("\(message)")
}
}
}
struct ThirdView_Previews: PreviewProvider {
static var previews: some View {
ThirdView(message: String())
}
}
Feedback is appreciated. Thanks!
remove the second navigation view
struct SecondView: View {
var message: String
var body: some View {
VStack(spacing: 100 ) {
Text("\(message)")
NavigationLink(destination: ThirdView(message: self.message)) {
Text("Go to Third View")
}
}
}
}
struct ThirdView: View {
var message: String
var body: some View {
Text("\(message)")
}
}

OnAppear and OnDisappear are not triggered on first view transition

I have a watchOS App which uses the following layout:
NavigationView {
if !HKHealthStore.isHealthDataAvailable() {
ContentNeedHealthKitView()
} else if !isAuthorized {
ContentUnauthorizedView()
} else {
TabView(selection: $selection) {
WeightView()
.navigationTitle("Weight")
.tag(1)
.onAppear {
print("Appear!")
}
.onDisappear {
print("Disappear!")
}
SettingsView()
.navigationTitle("Settings")
.tag(2)
}
}
}
Unfortunately, the OnAppear and OnDisappear actions are only executed after transitioning from on view to another the second time. When swiping right the first time, nothing happens.
You should provide a minimal reproducible example (see https://stackoverflow.com/help/minimal-reproducible-example).
Also your lines are producing compiler errors. The correct way to use onAppear is like this:
.onAppear {
}
Here is a working example, everything is working as expected. You should also place the onAppear ViewModifier to the child view.
import SwiftUI
struct WeightView: View {
var body: some View {
Text("WeightView")
.onAppear {
print("Appear!")
}
.onDisappear {
print("Disappear!")
}
}
}
struct SettingsView: View {
var body: some View {
Text("SettingsView")
}
}
struct ContentView: View {
#State var selection = 1
#State var isAuthorized = false
var body: some View {
NavigationView {
if !isAuthorized {
Button("authorize") {
isAuthorized.toggle()
}
} else {
TabView(selection: $selection) {
WeightView()
.navigationTitle("Weight")
.tag(1)
SettingsView()
.navigationTitle("Settings")
.tag(2)
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

How to redirect from one view to another view in SwiftUI?

I am using SwiftUI. I'm trying to move from list to details of a particular row of list. I've used code written below
struct StudentList: View {
var body: some View {
NavigationView {
List(studentData) { student in
NavigationLink(destination: studentDetail()) {
studentRow(student: student)
}
}
.navigationBarTitle(Text("Student Details"))
}
}
}
struct StudentList_Previews: PreviewProvider {
static var previews: some View {
StudentsList()
}
}
use this
List(studentData) { student in
NavigationLink.init("Here Title", destination: studentDetail())
}
struct ContentView: View {
let items = [1,2,3,4,5]
var body: some View {
NavigationView {
List(items, id: \.self) { inx in
NavigationLink(destination: DetailsView(inx: inx)) {
Text("\(inx)")
}
}
}
}
}
struct DetailsView: View {
var inx : Int
var body: some View {
VStack {
Text("\(inx)")
}
}
}
NavigationLink(destination: "provide your view here") {
}