SwiftUI - Pop back in navigation stack does not deallocate a view

Deadly 提交于 2020-05-16 03:16:48

问题


I would like to start by highlighting my views hierarchy. I just have FindUserView and WelcomeView.

FindUserView is used for retrieving users from the server if the entered email exists. If so, then it automatically redirects me to the next WelcomeView where I can enter password and login.

I've created a repo here and a video SwiftUI - Pop back does not deallocate view

My FindUserView: ---------------------------- and WelcomeView:

-----------------

By pressing NEXT button on FindUserView I fetch a user from the database:

func fetchUser(with email: String) {
        userService.getUser(with: email) { (result) in
            switch result {
            case .success(_):
                self.showActivityIndicator = false
                self.showingAlert = false
                self.showWelcomeView = true
                break
            case .failure:
                self.showingAlert = true
                break
            }
        }
    }

I use NavigationView and programatically show WelcomeView by changing showWelcomeView state above:

NavigationLink(destination: WelcomeView(), isActive: $showWelcomeView) { EmptyView() }

Now I am on welcome view WelcomeView.

But when I press this button and pop back, my WelcomeView still exists.

As I use @EnvironmentObject with observable property state I see how it reflects to the view which is already dismissed. Is this correct behaviour? Or do I need to dealloc WelcomeView somehow? Does it lead to memory leaks?

I am a bit worry as in UIKit when you pop back in navigation stack the view controller it is deallocated by UINavigationController by removing view controller from the array automatically. How to pop back correctly in SwiftUI?


回答1:


Actually it is not clear if it is defect or not - SwiftUI views are values, so there is no dealloc thing for them. It looks like NavigationView just keeps something like lastView variable until it is replaced with another one. Maybe worth submitting feedback to Apple.

Meanwhile here is solution that allows to defer real destination view creation until exactly NavigationLink tapped and cleanup it (w/ any related resources, like view model) when view is removed from stack by Back button.

Tested with Xcode 11.4 / iOS 13.4

Helper proxy view presenter:

struct LinkPresenter<Content: View>: View {
    let content: () -> Content

    @State private var invlidated = false
    init(@ViewBuilder _ content: @escaping () -> Content) {
        self.content = content
    }
    var body: some View {
        Group {
            if self.invlidated {
                EmptyView()
            } else {
                content()
            }
        }
        .onDisappear { self.invlidated = true }
    }
}

Usage:

NavigationLink(destination: LinkPresenter { WelcomeView() }, 
    isActive: $showWelcomeView) { EmptyView() }


来源:https://stackoverflow.com/questions/61448125/swiftui-pop-back-in-navigation-stack-does-not-deallocate-a-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!