首页 > 解决方案 > SwiftUI - 在导航堆栈中弹回不会取消分配视图

问题描述

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

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

我在这里创建了一个 repo和一个视频SwiftUI - Pop back does not deallocate view

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

在此处输入图像描述-----------------在此处输入图像描述

通过按下 NEXT 按钮,FindUserView我从数据库中获取用户:

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编程方式显示:WelcomeViewshowWelcomeView

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

现在我处于欢迎状态WelcomeView

但是当我按下这个按钮并弹回来时,我的WelcomeView仍然存在。

在此处输入图像描述

当我使用@EnvironmentObject可观察的属性状态时,我看到它如何反映到已经被忽略的视图中。这是正确的行为吗?还是我需要以WelcomeView某种方式解除分配?它会导致内存泄漏吗?

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

标签: iosswiftswiftuiios-navigationview

解决方案


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

同时,这里有一个解决方案,它允许推迟真正的目标视图创建,直到完全NavigationLink点击并清理它(w/任何相关资源,如视图模型),当视图通过后退按钮从堆栈中删除时。

使用 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() }

推荐阅读