【问题标题】:iOS Swiftui App returning to foreground reset ObservedObjectsiOS Swiftui App 返回前台重置 ObservedObjects
【发布时间】:2021-04-26 14:38:29
【问题描述】:

我有这个应用程序,它使用 ObservedObject 在各种视图之间共享数据。

定义视图模型

class MyViewModel: ObservableObject {
    @Published var language: String?
}

现在是内容视图

struct ContentView: View {
    @ObservedObject private var myViewModel = MyViewModel()

    var body: some View {
        Home()
        .environmentObject(self.myViewModel)
    }
}

这里是 Home()

struct Home: View {
    @EnvironmentObject var myViewModel: MyViewModel

    var body: some View {
        VStack {
            Text(self.myViewModel.language ?? "")
                .onReceive(self.myViewModel.$language, perform: { language in
                    print(language)
                })
            Button(action: {
                self.myViewModel.language = "American English"
            }, label: {
                Text("Set the language")
            })
        }
    }
}

onReceive 这里用于调试目的

点击按钮会将语言设置为“美式英语”,Text() 将显示更新后的字符串。

现在将应用置于后台,然后单击图标将其调回前台:尽管 UI 上没有任何更改,但 myviewmodel 为 NIL。

为了“恢复”状态,我修改了 ContentView 以接收“前台通知”,如此处所建议的 https://www.hackingwithswift.com/books/ios-swiftui/how-to-be-notified-when-your-swiftui-app-moves-to-the-background

struct ContentView: View {
    @ObservedObject private var myViewModel = MyViewModel()

    var body: some View {
        Home()
        .environmentObject(self.myViewModel)
        .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
           self.myViewModel.language = "American English"
        }
    }
}

Home() 的 onReceive 中的调试打印工作并显示正确的字符串,但 Text() 中的那个消失了,好像它收到了 nil 值并且没有后续刷新。

有什么想法吗?

编辑 必须保持 IOS 13 兼容性

【问题讨论】:

    标签: ios swift swiftui


    【解决方案1】:

    改用StateObject

    struct ContentView: View {
        @StateObject private var myViewModel = MyViewModel()
    
    ...
    

    【讨论】:

    • 我是个白痴,忘了说我需要保持 IOS 13 的兼容性。也编辑了问题。对不起@asperi
    • 然后在ContentView 之外创建MyViewModel() 并将其注入,例如AppDelegate,等等。实际上没有人说 ContentView 只创建一次,所以一旦重新创建(在你的情况下,放在前台)你就有了 MyViewModel 的新实例。
    • 我刚刚就如何在 scenedelegate 上设置它进行了一些斗争,但这似乎是答案。 @asperi 您能否添加一个答案(或编辑这个答案)以便给您应得的荣誉?
    猜你喜欢
    • 2020-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-25
    • 2016-11-25
    • 1970-01-01
    • 2020-09-02
    • 1970-01-01
    相关资源
    最近更新 更多