SwiftUI - 在导航堆栈中弹出不取消分配视图
SwiftUI - Pop back in navigation stack does not deallocate a view
我想首先突出显示我的视图层次结构。我只有 FindUserView
和 WelcomeView
.
如果输入的电子邮件存在,FindUserView
用于从服务器检索用户。如果是这样,它会自动将我重定向到下一个 WelcomeView
,我可以在其中输入密码并登录。
我创建了一个repo here and a video SwiftUI - Pop back does not deallocate view
我的 FindUserView
: -------------------------- 和 WelcomeView
:
-----------------
通过在 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
并通过更改上面的 showWelcomeView
状态以编程方式显示 WelcomeView
:
NavigationLink(destination: WelcomeView(), isActive: $showWelcomeView) { EmptyView() }
现在我在欢迎视图WelcomeView
。
但是当我按下这个按钮并弹出时,我的 WelcomeView
仍然存在。
当我将 @EnvironmentObject
与可观察的 属性 状态一起使用时,我看到它如何反映到已经被关闭的视图。这是正确的行为吗?或者我需要以某种方式解除分配 WelcomeView
吗?会不会导致内存泄露?
我有点担心 UIKit
当您在导航堆栈中弹出视图控制器时,它会被 UINavigationController
通过自动从数组中删除视图控制器来解除分配。 SwiftUI如何正确弹回?
实际上并不清楚它是否有缺陷 - SwiftUI 视图是值,所以它们没有 dealloc 东西。看起来 NavigationView
只是保留类似 lastView 的变量,直到它被另一个替换。也许值得向 Apple 提交反馈。
与此同时,这里的解决方案允许将真正的目标视图创建推迟到恰好 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() }
我想首先突出显示我的视图层次结构。我只有 FindUserView
和 WelcomeView
.
FindUserView
用于从服务器检索用户。如果是这样,它会自动将我重定向到下一个 WelcomeView
,我可以在其中输入密码并登录。
我创建了一个repo here and a video SwiftUI - Pop back does not deallocate view
我的 FindUserView
: -------------------------- 和 WelcomeView
:
通过在 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
并通过更改上面的 showWelcomeView
状态以编程方式显示 WelcomeView
:
NavigationLink(destination: WelcomeView(), isActive: $showWelcomeView) { EmptyView() }
现在我在欢迎视图WelcomeView
。
但是当我按下这个按钮并弹出时,我的 WelcomeView
仍然存在。
当我将 @EnvironmentObject
与可观察的 属性 状态一起使用时,我看到它如何反映到已经被关闭的视图。这是正确的行为吗?或者我需要以某种方式解除分配 WelcomeView
吗?会不会导致内存泄露?
我有点担心 UIKit
当您在导航堆栈中弹出视图控制器时,它会被 UINavigationController
通过自动从数组中删除视图控制器来解除分配。 SwiftUI如何正确弹回?
实际上并不清楚它是否有缺陷 - SwiftUI 视图是值,所以它们没有 dealloc 东西。看起来 NavigationView
只是保留类似 lastView 的变量,直到它被另一个替换。也许值得向 Apple 提交反馈。
与此同时,这里的解决方案允许将真正的目标视图创建推迟到恰好 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() }