skip to Main Content

I currently have an application with 4 tab views

Content View:

import SwiftUI

struct ContentView: View {

init() {
    
    //Setting appearance of UI colour
    UITabBar.appearance().backgroundColor = ColourManager.UIColour1
}

var body: some View {
    
    
    TabView {
        ProfileView().tabItem ({
            Text("Profile")
        }).tag(0)
        
        TrackerView().tabItem ({
            Text("Tracker")
        }).tag(1)
        
        ProgressView().tabItem ({
            Text("Progress")
        }).tag(2)
        
        MealView().tabItem ({
            Text("Meals")
        }).tag(3)
    }.accentColor(ColourManager.Colour3)
    
    }

}

And I have the following class which is my model:

import Foundation

class UserInfoModel: ObservableObject {


struct UserInfo: Identifiable {
    var id = UUID()
    var height: Int
    var weight: Int
    var gender: String
    var age: Int
    
}

struct DailyCalorieGoals: Identifiable{
    var id = UUID()
    var calorieGoal: Int
    var fatGoal: Int
    var proteinGoal: Int
    var carbGoal: Int

}

struct CurrentCalorieProgress: Identifiable{
    var id = UUID()
    var calorieProgress: Int
    var fatProgress: Int
    var proteinGoal: Int
}

@Published var person1 = UserInfo.init(height: 20, weight: 30, gender: "male", age: 5)

}

Now what I am trying to do is create a single instance of this class and have all my views access the same object using Observable Object, however in my first view, I set the weight to a new value to check if it maintains that state in my other view:

ProfileView

@ObservedObject var person = UserInfoModel()

    
    var body: some View {
        Button(action: {
            print(self.person.person1.weight)
            self.person.person1.weight = 100
            print(self.person.person1.weight)
        }) {
            Text("Button")
        }
        .foregroundColor(ColourManager.Colour1)
       
    }
    
}

Which changes the value of weight to 100 but when I go to another tab screen, and instantiate the object again, the value goes back to the one declared in the model class:

 @ObservedObject var person = UserInfoModel()

    
    var body: some View {
        Button(action: {
                print(person.person1.weight)
            
        }) {
            Text("Button")
        }
        .foregroundColor(ColourManager.Colour1)

        
        
        
    }
}

So I essentially want to just instantiate one object, and be able to manipulate it and change the values in all views and update the UI automatically, any help would be greatly appreciated!

2

Answers


  1. Thats because you are creating a new instance of UserInfoModel for each view .. you have to create that once in the first view and pass it to your subviews as parameter or even as environment object.

    @ObservedObject var person: UserInfoModel //<< just declare typ and pass it from main view
    

    And in your ContentView you will create that Model once

    Login or Signup to reply.
  2. 1. Using ObservedObject

    @ObservedObject is used to keep track of an object that has already been created, probably using @StateObject.
    You have to create the person variable in the ContentView, where the TabView is created

    @StateObject var person = UserInfoModel()
    

    And pass it as a parameter to each View from the TabView

     ProfileView(person: person).tabItem ({
            Text("Profile")
        }).tag(0)
    

    And now in each view you remove the instantiation of person variable, you keep just the declaration

    @ObservedObject var person: UserInfoModel
    

    2. Using EnvironmentObject

    @EnvironmentObject is recommended for those scenarios where you need to use an @ObservableObject but the views aren’t direct parent/child pairs.

    In your App file you’d have to create the person object:

    @StateObject var person = UserInfoModel()
    

    And the pass it to the ContentView like this:

    ContentView().person(person)
    

    To use the object in any view that is within ContentView , you do this:

    @EnvironmentObject var person: UserInfoModel
     
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search