New iOS Dev
New iOS Dev

Reputation: 2057

How to observe change in @StateObject in SwiftUI?

I am having property with @StateObject, I am trying to observe change in viewmodel, I am able to print correct result but can not able to show on screen as view is not refreshing.

Tried using binding but not worked because of @StateObject

import SwiftUI
struct AbcView: View {

    @StateObject var abcViewModel: AbcViewModel

    init(abcViewModel: AbcViewModel) {
        self._abcViewModel = StateObject(wrappedValue: abcViewModel)
    }

    var body: some View {
        VStack(alignment: .leading) {
            ZStack(alignment: .top) {
                ScrollView {
                    Text("some txt")
                }
                .overlay(
                    VStack {
                        TopView(content: classViews(data: $abcViewModel.somedata, abcViewModel: abcViewModel))
                        Spacer()
                    }
                )
            }
        }
    }
}

func classViews(data: Binding<[SomeData]>, abcViewModel: AbcViewModel) -> [AnyView] {
    var views: [AnyView] = []

    for element in data {
        views.append(
            VStack(spacing: 0) {
                HStack {
                    print("\(abcViewModel.title(Id: Int(element.dataId.wrappedValue ?? "")) )") // printing correct value
                    Text(abcViewModel.title(Id: Int(element.dataId.wrappedValue ?? ""))) // want to observe change here
                }
            }
                .convertToAnyView())
    }
    return views
}

Upvotes: 1

Views: 1967

Answers (1)

Mr.SwiftOak
Mr.SwiftOak

Reputation: 1834

If you are injecting your AbcViewModel into AbcView you should use @ObserverdObject instead of @StateObject , full explanation here Also you should conform tour AbcViewModel to ObservableObject and make your desired property @Published if you want to trigger the change in View . Here is simplified code example:

  1. Making AbcViewModel observable:

    class AbcViewModel: ObservableObject {
     @Published var dataID: String = "" //by changing the @Published   proprty you trigger change in View using it
    }
    
  2. store AbcViewModel as @ObserverdObject:

    struct AbcView: View {
     @ObservedObject var abcViewModel: AbcViewModel
    
     init(abcViewModel: AbcViewModel) {
         self.abcViewModel = abcViewModel
     }
    
     var body: some View {
        //...
     }
    }
    
  3. If you now use your AbcViewModel dataID property anywhere in the project, and you change its value, the property will publish the change and your View (struct) will be rebuilded. Use the same pattern for creating TopView and assigning AbcViewModel to it the same way.

Upvotes: 3

Related Questions