3

I want to init a navigation stack in SwiftUI. Thus I want to push a second view immediately after a first view appears. Therefore I want to use a @State var, which I set to true onAppear, and thus activates a NavigationLink.

However, the approach is not working (without modifications, see below). The push is done and then the second view is immediately dismissed (video). This is my sample (Github Repo):

struct SecondView: View {
  var body: some View {
    Text("Second")
      .navigationTitle("Second")
      .onAppear(perform: {
        print("Second: onAppear")
      })
  }
}

struct FirstView: View {
   @State var linkActive = false

   var body: some View {
     NavigationLink(destination: SecondView(), isActive: $linkActive) {
       Text("Goto second")
     }
     .navigationTitle("First")
     .onAppear(perform: {
       print("First: onAppear")
       linkActive = true
     })
     .onChange(of: linkActive) { value in
       print("First: linkActive changed to: \(linkActive)")
     }
   }
 }

 struct SwiftUIView: View {
   var body: some View {
     NavigationView {
       NavigationLink(destination: FirstView()) {
         Text("Goto first")
       }
     }
     .navigationViewStyle(StackNavigationViewStyle())
   }
}

Output:

First: onAppear
First: linkActive changed to: true
Second: onAppear
First: linkActive changed to: false

If I modify the onAppear to set the linkActive to true after a delay of min. 0.5 seconds it works. What is wrong here? I expect the SecondView to stay on screen as I don’t get why isActive is changed back to false.

honkmaster
  • 31
  • 2
  • The problem is because you are using a local state if you can create an abstract view or using delegate if it support that. Check out this article if it can help you https://code.tutsplus.com/tutorials/the-right-way-to-share-state-between-swift-view-controllers--cms-28474 – Michael Dec 27 '20 at 13:28
  • 1
    I am using a local @State sure. But I do not see how your commend and the link is related to my question. I am not sharing data between views on purpose. – honkmaster Dec 27 '20 at 14:12
  • any time you try to persist a data is called sharing of data and what you are trying to do is you re telling your second view to modify the first view data which is not going to work unless if your data is a global delegate and the article sent to you suppose to gives more clear picture of what to do in a better approach. – Michael Dec 27 '20 at 14:31
  • The problem you are encounter is because all classes are private or secure – Michael Dec 27 '20 at 14:32
  • 1
    Either I'm totally stupid and don't understand your comment or we're talking past each other. The second view does nothing active, it has no access to the NavigationLink that is used to show it. I'm using basic concepts from SwiftUI here. And with your comment about private, public classes ... it doesn't get any better (did you see we are using structs here). I am feeling trolled. – honkmaster Dec 27 '20 at 15:04
  • i don't know if this link can help you finally https://stackoverflow.com/questions/60797431/how-to-trigger-a-navigationlink-programmatically-on-appear?rq=1 – Michael Dec 27 '20 at 15:32
  • I tried isActive.toggle instead of isActive = true. No change. Added a repo link and video above for anyone who wants to try and see it for themselves. – honkmaster Dec 27 '20 at 20:47
  • 1
    I must have misread your original post because I independently discovered that if I change isActive to true after 0.5 seconds it works. I only tested increments of 0.1s, but all I can offer is another data point that I see the same behavior. 0.4s and it returns immediately. 0.5 and it stays on `SecondView`. – drootang Dec 28 '20 at 16:47

0 Answers0