9

I've already read this existing thread on the issue and comments indicate that this is a bug and has been fixed on 11.7, but I'm still running into it on that version.

In summary:

when the app starts, your view View 1 fires an onAppear.

when I navigate to a child view (View 2) using a Navigation Controller , there is no onDisappear fired for View 1, but an onAppear does fire for View 2.

When you navigate back to View 1, you do not get a onAppear for View 1 or an onDisappear for (view 2).

Is there a workaround for a reliable way to trigger events when views appear/disappear? Or should I try hopping to the Xcode beta?

Example Code:

  import SwiftUI
    
    struct DetailView: View {
        var body: some View {
            Text("Detail view")
            .onAppear(){
                print("DetailView onAppear fired")
            }
            .onDisappear(){
                print("DetailView onDisappear fired")
            }
        }
    }
    
    
    struct ContentView: View {
        var body: some View {
            NavigationView {
                NavigationLink(destination: DetailView()) {
                    Text("Show detail view")
                }
                .navigationBarTitle("Master view")
            }
            .onAppear(){
                print("ContentView onAppear fired")
            }
            .onDisappear(){
                print("ContentView onDisappear fired")
            }
        }
    }
pkamb
  • 33,281
  • 23
  • 160
  • 191
  • Can you provide a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example)? – pawello2222 Sep 10 '20 at 21:58
  • added! fwiw the onDisappear for detailView did fire, so I guess the problem is the onAppear for the contentView only gets fired on initial loading. – HelveticaGoodTime Sep 10 '20 at 22:08
  • This is just how SwiftUI works. Instead of `onAppear` in the ContentView, you can use `onDisappear` in the DetailView. But if you explain *why* do you need it, you might get a better answer. – pawello2222 Sep 10 '20 at 22:12
  • ah ok this is great to know. I thought onAppear would fire every time I returned to the view. I'm using them to manage Firebase Snapshot Listeners. I think knowing that the onDisappear at least works I can solve my problem. Thanks so much! – HelveticaGoodTime Sep 10 '20 at 22:17

1 Answers1

23

You have added onAppear {..} and onDisappear {..} to the NavigationView which is still visible/appears in the DetailView. I guess, what you are getting is expected behaviour. onDisappear {..} will be called only when view go off from screen.

Adding onAppear {..} and onDisappear {..} to your Text view will give the result as you expected.

Updated ContentView:

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: DetailView()) {
                Text("Show detail view")
                .onAppear {
                    print("ContentView onAppear fired")
                }
                .onDisappear {
                    print("ContentView onDisappear fired")
                }
            }
            .navigationBarTitle("Master view")
        }
    }
}

Output of the updated code:

ContentView onAppear fired
DetailView onAppear fired
ContentView onDisappear fired
ContentView onAppear fired
DetailView onDisappear fired

Thanks! ‍

Karthick Selvaraj
  • 2,387
  • 17
  • 28