SwiftUI在推送视图中加载数据或在弹出视图中重置

时间:2020-05-20 21:59:10

标签: ios swift swiftui

Swift 5.2
我有一个NavigationView,用于由NavigationLinks连接的视图树。 (没有奇怪的情况发生;在树的不同部分之间没有循环或跳跃-只是链接到子视图的视图链接到了子子视图。)其中之一是配置屏幕。我希望当您到达配置屏幕(即ConfigView)时,配置是从磁盘加载的。在ConfigView的子视图中,可以修改不同的设置,在ConfigView上,可以保存设置。但是,我希望如果弹出ConfigView(离开,移至树的根),则未保存的更改将被丢弃。

我最初的想法之一是将更改加载到ConfigView初始化程序中。这是行不通的,因为在父视图中调用了ConfigView(),因此退出ConfigView并返回ConfigView会在视图之间保持相同的ConfigView(并因此保留相同的脏数据)。 (...或者,ConfigView被多次重新创建而没有实际离开它,从而导致错误地重新加载了数据。我试图测试一下它在什么条件下进行了操作,只是现在,但是遇到了崩溃,我不会无论如何,我今天早些时候都对其进行了测试,并且证明了上述一种或两种行为。) 也许将其加载到身体块中?但这可以重新运行,例如当您从子视图链接返回时,会错误地重新加载数据。 也许将其加载到.onAppear中?但是,当您从子视图返回时,该操作还会错误地重新加载数据。 我考虑了我的初衷,可能会在弹出ConfigView时处理脏数据(并在需要时重新加载),但是我没有发现任何钩子可以用来通知例如用户点击“后退”按钮。

如何获取新的数据的干净副本,该数据将出现在ConfigView的新条目中,并且在弹出ConfigView之前不会丢失?

1 个答案:

答案 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()
    }
}