SwiftUI-在导航堆栈中弹出不会取消分配视图

时间:2020-04-26 21:09:14

标签: ios swift swiftui ios-navigationview

我首先要突出显示我的视图层次结构。我只有FindUserViewWelcomeView

FindUserView用于从服务器中检索用户(如果输入的电子邮件存在)。如果是这样,那么它将自动将我重定向到下一个WelcomeView,我可以在其中输入密码并登录。

我已经创建了repo here和视频SwiftUI - Pop back does not deallocate view

我的FindUserView:----------------------------和WelcomeView

enter image description here ----------------- enter image description here

通过按下FindUserView上的NEXT按钮,我从数据库中提取了一个用户:

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
            }
        }
    }

我使用NavigationView并通过更改上面的WelcomeView状态以编程方式显示showWelcomeView

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

现在我处于欢迎视图WelcomeView

但是当我按下此按钮并弹出时,我的WelcomeView仍然存在。

enter image description here

当我将@EnvironmentObject与可观察的属性状态一起使用时,我会看到它如何反映已被关闭的视图。这是正确的行为吗?还是我需要以某种方式取消分配WelcomeView?会导致内存泄漏吗?

我有点担心,因为在UIKit中,当您从导航堆栈中弹出视图控制器时,UINavigationController会通过自动从阵列中删除视图控制器来将其释放。如何在SwiftUI中正确弹出?

1 个答案:

答案 0 :(得分:1)

实际上尚不清楚是否有缺陷-SwiftUI视图是值,因此没有 dealloc 东西。看起来NavigationView只是保留了 lastView 这样的变量,直到被另一个变量替换为止。也许值得向苹果提交反馈。

与此同时,这是一种解决方案,当通过“后退”按钮从堆栈中删除视图时,可以推迟创建实际目标视图,直到准确NavigationLink轻按并清理它(带有任何相关资源,例如视图模型)。

通过Xcode 11.4 / iOS 13.4测试

助手代理视图演示者:

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 }
    }
}

用法:

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