Swift 5.2
我有一个NavigationView,用于由NavigationLinks连接的视图树。 (没有奇怪的情况发生;在树的不同部分之间没有循环或跳跃-只是链接到子视图的视图链接到了子子视图。)其中之一是配置屏幕。我希望当您到达配置屏幕(即ConfigView)时,配置是从磁盘加载的。在ConfigView的子视图中,可以修改不同的设置,在ConfigView上,可以保存设置。但是,我希望如果弹出ConfigView(离开,移至树的根),则未保存的更改将被丢弃。
我最初的想法之一是将更改加载到ConfigView初始化程序中。这是行不通的,因为在父视图中调用了ConfigView(),因此退出ConfigView并返回ConfigView会在视图之间保持相同的ConfigView(并因此保留相同的脏数据)。 (...或者,ConfigView被多次重新创建而没有实际离开它,从而导致错误地重新加载了数据。我试图测试一下它在什么条件下进行了操作,只是现在,但是遇到了崩溃,我不会无论如何,我今天早些时候都对其进行了测试,并且证明了上述一种或两种行为。)
也许将其加载到身体块中?但这可以重新运行,例如当您从子视图链接返回时,会错误地重新加载数据。
也许将其加载到.onAppear
中?但是,当您从子视图返回时,该操作还会错误地重新加载数据。
我考虑了我的初衷,可能会在弹出ConfigView时处理脏数据(并在需要时重新加载),但是我没有发现任何钩子可以用来通知例如用户点击“后退”按钮。
如何获取新的数据的干净副本,该数据将出现在ConfigView的新条目中,并且在弹出ConfigView之前不会丢失?
答案 0 :(得分:0)
您应该在应用程序中的某个位置具有持久性数据,并且在将数据传递到子视图时,请创建草稿数据(ObservableObject)。然后,在需要时将更新的数据保存到持久性数据。这样,孩子将仅使用草稿数据,而您的父视图将仅显示持久性数据。
这里有一个很好的例子:https://developer.apple.com/tutorials/swiftui/working-with-ui-controls
请查看Apple制作的所有教程,它们都是简短而强大的示例。
我会将上面链接中的代码粘贴到此处,以防将来代码丢失。
struct ProfileHost: View {
@Environment(\.editMode) var mode
@EnvironmentObject var userData: UserData
@State var draftProfile = Profile.default
var body: some View {
VStack(alignment: .leading, spacing: 20) {
HStack {
if self.mode?.wrappedValue == .active {
Button("Cancel") {
self.draftProfile = self.userData.profile
self.mode?.animation().wrappedValue = .inactive
}
}
Spacer()
EditButton()
}
if self.mode?.wrappedValue == .inactive {
ProfileSummary(profile: userData.profile)
} else {
ProfileEditor(profile: $draftProfile)
.onAppear {
self.draftProfile = self.userData.profile
}
.onDisappear {
self.userData.profile = self.draftProfile
}
}
}
.padding()
}
}