SwiftUI - 在导航堆栈中弹回不会取消分配视图
Posted
技术标签:
【中文标题】SwiftUI - 在导航堆栈中弹回不会取消分配视图【英文标题】:SwiftUI - Pop back in navigation stack does not deallocate a view 【发布时间】:2020-04-26 21:09:14 【问题描述】:我想首先突出显示我的视图层次结构。我只有FindUserView
和WelcomeView
。
FindUserView
用于在输入的电子邮件存在时从服务器检索用户。如果是这样,它会自动将我重定向到下一个WelcomeView
,我可以在其中输入密码并登录。
我创建了一个repo here 和一个视频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 中正确弹回?
【问题讨论】:
【参考方案1】:实际上并不清楚它是否是缺陷 - 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()
【讨论】:
好的,谢谢!让我试试你的解决方案,我也向 Apple 提交了一个问题。让我们看看他们会评论什么。 Apple 依靠我的下一个(不确定我是否理解):数据需要控制是否正在进行工作。查看代码,WelcomeView 中的状态似乎是错误的。 showActivityIndicator 在获取开始时设置为 true,但没有设置为 false。该属性不应该是视图的状态,而应该是执行获取的对象的属性。当 fetch 停止时活动指示器将停止,并且视图在空闲时不会消耗任何资源。以上是关于SwiftUI - 在导航堆栈中弹回不会取消分配视图的主要内容,如果未能解决你的问题,请参考以下文章
在 SwiftUI 中将绑定传递给导航堆栈中每个视图的最佳方法是啥
SwiftUI 垂直 ScrollView 弹回并不显示其中的所有视图