swiftswiftuibindinginitializationswiftui-state

Publishing a Var from Another @ObservableObject During Init()


How does one publish a property from another ObservableObject which is created during initialization?

I want to ensure a specific property is captured as a @Published/@Binding/@State variable (so it's always kept updated in views), but I'm encountering an error when binding from an object that's also being created during the same init(). For example:

The RandomOptionsManager is an ObservableObject which loads a list of options from a file:

class RandomOptionsManager: ObservableObject {
    
    @Published var listCount: Int = 0
    
    init() {
        // Real code would load the list from a file
        self.listCount = 150
    }
}

The Randomizer which uses it has a count property for how many options are available. I'm trying to get this as a @Binding from the @Published var in the options manager:

class Randomizer: ObservableObject {
    
    @ObservedObject var optionsManager = RandomOptionsManager()
    @Binding var listCount: Int
    
    init() {
        self._listCount = $optionsManager.listCount
    }
}

However, this code results in an init error:

'self' used in property access '$optionsManager' before all stored properties are initialized

What's the correct configuration to avoid this issue?


Solution

  • As suggested in the question comments, this can be solved by avoiding @Binding & @ObservedObject (which are really for views, rather than other classes like this) and using assign(to:) to republish the optionsManager's @Published var as a new property.

    This only requires code changes for the Randomizer (the code for RandomOptionsManager remains unchanged):

    class Randomizer: ObservableObject {
        
        @Published var listCount: Int = 0
        private let optionsManager = RandomOptionsManager()
        
        init() {
            optionsManager.$listCount.assign(to: &self.$listCount)
        }
    }
    

    Note that assign(to:) automatically handles life-cycle management, so a separate explicit assignment to cancellable is not required.