How to trigger onAppear when returning from fullScreenCover

492 Views Asked by At

onAppear doesn't trigger

struct ProfileView: View {
    @StateObject var viewModel = ProfileViewViewModel()
    var body: some View {
        NavigationView {
            VStack {
                if let user = viewModel.user {
                    profile(user: user)
                } else {
                    Text("Loading Profile...")
                }
            }
            .navigationTitle("Profile")
        }
        .onAppear {
            viewModel.fetchUser() //this is the problem
        }
        .fullScreenCover(isPresented: $viewModel.showingPreview) {
            PreviewAvatarView()
        }
    }
}

I realized that onAppear didn't trigger when I dismiss fullscreencover.

3

There are 3 best solutions below

0
ScottM On BEST ANSWER

The onAppear doesn’t trigger because your underlying view is not appearing – the view that is covering it is going away, which isn’t the same thing.

However, fullScreenCover has a rarely-used optional argument, onDismiss, which may fulfil your needs, e.g.:

.fullScreenCover(
  isPresented: $viewModel.showingPreview,
  onDismiss: { viewModel.fetchUser() }
) {
  PreviewAvatarView()
}

Apple documentation

6
lorem ipsum On

Instead of using onAppear you can use task.

struct ProfileView: View {
    @StateObject var viewModel = ProfileViewViewModel()
    var body: some View {
        NavigationView {
            VStack {
                if let user = viewModel.user {
                    profile(user: user)
                } else {
                    Text("Loading Profile...")
                }
            }
            .navigationTitle("Profile")
        }
        .task(id: viewModel.showingPreview) {
            guard !viewModel.showingPreview else {return} //Check for false
    
            viewModel.fetchUser() //this is the problem
        }
        .fullScreenCover(isPresented: $viewModel.showingPreview) {
            PreviewAvatarView()
        }
    }
}

task will run onAppear and when the Bool is false.

0
Kapil Shanbhag On

You can try this solution.

struct ProfileView: View {
    @StateObject var viewModel = ProfileViewViewModel()
    var body: some View {
        NavigationView {
            VStack {
                if let user = viewModel.user {
                    profile(user: user)
                } else {
                    Text("Loading Profile...")
                }
            }
            .navigationTitle("Profile")
        }
        .onAppear {
            viewModel.fetchUser() //this is the problem
        }
        .fullScreenCover(isPresented: $viewModel.showingPreview) {
            PreviewAvatarView()
        }
        .onChange(of: viewModel.showingPreview) { isFullScreenOpen in
            if !isFullScreenOpen {
                viewModel.fetchUser()
            }//Executed only when full screen cover is closed.
        }
    }
}

Whenever the sheet closes the viewModel.fetchUser() will be executed.