Hi. this is my observable object
final class ToolbarItemProperties: ObservableObject {
var visible = false
var disabled = false
var icon = "questionmark"
var action: () -> Void = { }
var opacity: Double = 1
}
the opacity property value should either be 0.5 or 1 depending on the value of the property disabled. How to listen to it?
The purpose for this is because if i set a button to disabled, it does not render any way to the user to let them know it is disabled. So i thought of changing the opacity instead, hence the opacity property.
So if i do something like this
item.disabled = true
the opacity property value should become 0.5. if disabled is set to false, the opacity value will be 1.
The issue you have is that ToolbarItemProperties
is a class, and an instance of that class is stored in an @Published
variable inside of an ObservableObject
class. This AppData
class is expected to watch the toolbarItem1
property for any changes (and then update the UI) but, because of the nature of a class, the difference between one before and after a variable change isn't as easily noticeable. If ToolbarItemProperties
was a struct this wouldn't be a problem.
Because of this, you will need to manually publish changes to tell SwiftUI in advance that a variable is going to change and to reload the UI. This is done by using the provided property of the ObservableObject
protocol:
objectWillChange.send()
Since you didn't provide any example code, I have created some which shows this working:
final class ToolbarItemProperties {
var visible = false
var disabled = false
var icon = "questionmark"
var action = {}
var opacity: Double {
disabled ? 0.5 : 1
}
}
final class AppData: ObservableObject {
@Published var toolbarItem1: ToolbarItemProperties?
}
struct ContentView: View {
@StateObject private var appData: AppData
init() {
let appData = AppData()
appData.toolbarItem1 = ToolbarItemProperties()
_appData = StateObject(wrappedValue: appData)
}
var body: some View {
VStack(spacing: 20) {
Text("Hello, World!")
.opacity(appData.toolbarItem1?.opacity ?? 1)
let toggleBinding = Binding<Bool> {
appData.toolbarItem1?.disabled == true
} set: {
// This line is the key part
// Must be before the variable change
appData.objectWillChange.send()
appData.toolbarItem1?.disabled = $0
}
Toggle("Is Disabled", isOn: toggleBinding)
.toggleStyle(.button)
}
}
}