I have such a simple checkmark SwiftUI view. It is displayed in a List and can be toggled by tapping on it or can be toggled when refreshed from a data source (ex. Core Data)
My First implementation was
struct RoundedCheckmark: View {
@State var isChecked : Bool
let onCheck: (Bool) -> Void
func toggle() { isChecked = !isChecked; onCheck(isChecked) }
init(isChecked: Bool, onCheck: @escaping (Bool) -> Void = { _ in }) {
self._isChecked = State(initialValue: isChecked)
self.onCheck = onCheck
}
var body: some View {
Button(action: toggle) {
Image(isChecked ? "CheckedCheckmark" : "UncheckedCheckmark")
}
}
}
It seemed to work I could toggle it and it loads correctly. On toggle, I saved changed via onCheck closure/callback and it refreshed ok.
But after external refreshes like push notification refreshing underlying model in Core Data refresh of this View doesn't correctly change @State property isChecked.
In init() I am getting new value of isChecked and reinitialized @State with State(initialValue: ). But in the body, I am getting the old value of isChecked as from old @State property. so the view does have the wrong image.
Here is workaround i.e. relying only on let isChecked property and onCheck callback. But now I cannot have state inside my View, and I have to only rely on external data source change. Maybe it is more appropriate as this way I have a single source of truth without local @State storage.
struct RoundedCheckmark: View {
let isChecked: Bool
let onCheck: (Bool) -> Void
func toggle() { onCheck(isChecked) }
init(isChecked: Bool, onCheck: @escaping (Bool) -> Void = { _ in }) {
self.isChecked = isChecked
self.onCheck = onCheck
}
var body: some View {
Button(action: toggle) {
Image(isChecked ? "CheckedCheckmark" : "UncheckedCheckmark")
}
}
}