Valerio
Valerio

Reputation: 3614

iOS Swiftui App returning to foreground reset ObservedObjects

I have this app that use ObservedObject to share data across various views.

Defining the viewmodel

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

Now for ContentView

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

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

Here is 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 here is used for debug purposes

clicking the button will set language to "American English" and the Text() will show the updated string.

Now put the app on background and then click the icon to call it back to foreground: despite nothing changed on the UI, myviewmodel is NIL.

To "restore" the state, I've modified ContentView to receive a "foreground notification", as suggested here 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"
        }
    }
}

The debug print in Home()'s onReceive works and shows the correct string, but the one in Text() disappear, as if it receive the nil value and get no subsequent refresh.

Any idea?

EDIT Must keep IOS 13 compatibility

Upvotes: 2

Views: 1793

Answers (1)

Asperi
Asperi

Reputation: 257789

Use instead StateObject

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

...

Upvotes: 2

Related Questions