0

So I am currently working on my app and have come across a problem where I have to access a published variable in another observable class.

Here is some code on what I am trying to do

class PeriodViewModel: ObservableObject {
    @Published var value = 1
}



class DataViewModel: ObservableObject {
    @ObservedObject var periodViewModel = PeriodViewModel()

    periodViewModel.value = 1
}

How would I be able to access the updated variable from periodViewModel in dataViewModel? Thanks.

GoddlyGut
  • 3
  • 5
  • Look into sink from combine. But technically view models should never know about each other. You should move the data down to a manager or store – lorem ipsum Nov 30 '22 at 00:04
  • Are you by any chance able to give me some sort of example on how it would be used in this example? – GoddlyGut Nov 30 '22 at 00:22
  • https://stackoverflow.com/search?q=Sink+observableobject – lorem ipsum Nov 30 '22 at 00:51
  • if you want to digg in the mechanism of observables i had a similar question focusing backward compatibility and use cases outside Viewmodels. https://stackoverflow.com/questions/72660391/declare-property-like-publisher-in-swift-version-that-doesnt-support-this-featu – Ol Sen Nov 30 '22 at 02:29
  • @Published object trigger the re-render to views that are listing them. Classes does't shows there behaviour neither we need of these because simple variables can be accessible from one class to other class. – Qazi Ammar Nov 30 '22 at 06:42
  • Ok but for my example, if I am storing a published variable in one class, and my data manager code is in the other. The data manager receives data from firebase and then sets the assigned variable. How does the UI update with the updated data? – GoddlyGut Nov 30 '22 at 12:31
  • each firebase observer have its callback you need to listen these call back into your `ObservableObject` class and update your publisher values into these callbacks. We you change the `@Publisher` SwiftUI Automatically re-render your view. – Qazi Ammar Nov 30 '22 at 13:28
  • you shouldn't usually have more than one class in SwiftUI, look into `@State` and `@Binding` to make the view struct like an object. And use the `.task` modifier for networking. – malhal Nov 30 '22 at 13:41

1 Answers1

0

[Note]: Ignore all the variables I am just showing the the flow of using different mangers.

Here is an example of function that I am using for my FirebaseDatabaseManage. You can see a clouser is passing into the function parameter. When your firebase insert function response after async you need to call your clouser which I named as completion.

class FirebaseDatabaseManager {
    
    
    public func insertRecipe(with recipe: RecipeModel, completion: @escaping (Bool, String) -> Void) {
        
        SwiftSpinner.show("Loading...")
        let userID = UserDefaultManager.shared.userId
        
        database.child(FireBaseTable.recipes.rawValue).child(userID).childByAutoId().setValue(recipe.convertToDictionary!, withCompletionBlock: { error, ref in
            
            SwiftSpinner.hide()
            
            guard error == nil else {
                completion(false, "failed to write to database")
                return
            }
            
            completion(true, ref.key ?? "no key found")
            
        })
    }
}

Now look at my ViewModel class in which I am calling my FirebaseManager method. On calling of completion I am updating my @Publisher Which you can use to update your UI.

class RecipeViewModel: ObservableObject {

  @Publisher var id = 0
    
    func createRecipe() {
        
        FirebaseDatabaseManager.shared.insertRecipe(with: self.recipeModel) { status, id in
            
            self.id = id
        }
    }
}

Hope this help your in understand your concepts.

Qazi Ammar
  • 953
  • 1
  • 8
  • 23