Recently I have noticed an interesting thing when using the Observable annotation. I have a model marked with Observable, and there is an array in the model, at some point I call the removeAll on this array using a where condition, and even though the condition isnt matching, and nothing is removed from the array, I noticed the observation is being triggered, and swiftui thinks the array is changed, but in reality the array is unchanged. Why is this happening ?
struct ObservableArrayTestView: View {
@State var model = AppModel()
var body: some View {
let _ = Self._printChanges()
Button {
model.removeCard()
} label: {
Text(model.title)
}
}
}
and model:
@MainActor @Observable
class AppModel {
var cards: [String] = []
var title: String {
cards.isEmpty ? "" : "Cards (\(cards.count))"
}
init() {
cards = (1...20).map { "Card \($0)" }
}
func removeCard() {
cards.removeAll(where: { $0 == "test" })
}
}
here is what I see when button is tapped:
ObservableArrayTestView: \AppModel.cards changed.
ObservableArrayTestView: \AppModel.cards changed.
ObservableArrayTestView: \AppModel.cards changed.
ObservableArrayTestView: \AppModel.cards changed.
how can we avoid from this observation to happen ? I understand, we can add a guard check that only call removeAll if it contains in the array, and this observation wouldn't happen.
Why is removeAll changing the array ? I even checked the array memory address, it is same, so how is this observation change coming ?