I have a rather strange problem with animation on adding elements to list in SwiftUI. I have a simple model class:
struct ShoppingList: Identifiable, Equatable {
let id: UUID
var name: String
var icon: String
var items: [Item]
init(id: UUID = UUID(), name: String, icon: String, items: [Item] = []) {
self.id = id
self.name = name
self.icon = icon
self.items = items
}
static func == (lhs: ShoppingList, rhs: ShoppingList) -> Bool {
return lhs.id == rhs.id
}
}
extension ShoppingList {
struct Item: Identifiable, Equatable {
let id: UUID
var name: String
init(id: UUID = UUID(), name: String) {
self.id = id
self.name = name
}
static func == (lhs: Item, rhs: Item) -> Bool {
return lhs.id == rhs.id
}
}
}
When I pass single ShoppingList object as binding to the view, adding animation basically doesn't happen at all:
Here is code of my view:
struct ShoppingListDetailView: View {
@Binding var shoppingList: ShoppingList
@State private var newItemName = ""
var body: some View {
List {
ForEach($shoppingList.items) { $item in
Text(item.name)
}
HStack {
TextField("Add item", text: $newItem)
Button(action: addNewItem) {
Image(systemName: "plus.circle.fill")
}
.disabled(newItemName.isEmpty)
}
}
.navigationTitle(shoppingList.name)
}
private func addNewItem() {
withAnimation {
let newItem = ShoppingList.Item(name: newItemName)
shoppingList.items.append(newItem)
}
}
}
And here is code of a parent view:
struct ShoppingListsView: View {
@Binding var shoppingLists: [ShoppingList]
var body: some View {
List {
ForEach($shoppingLists) { $list in
NavigationLink(destination: ShoppingListDetailView(shoppingList: $list)) {
ShoppingListItemView(shoppingList: $list)
}
}
}
.navigationTitle("Shopping List")
}
}
But once I pass whole list of ShoppingList objects and index for a particular one, everything works as expected:
Code with passing list to the view looks like that:
struct ShoppingListDetailView: View {
@Binding var shoppingList: [ShoppingList]
var index: Int
@State private var newItemName = ""
var body: some View {
List {
ForEach($shoppingList[index].items) { $item in
Text(item.name)
}
HStack {
TextField("Add item", text: $newItem)
Button(action: addNewItem) {
Image(systemName: "plus.circle.fill")
}
.disabled(newItemName.isEmpty)
}
}
.navigationTitle(shoppingList[index].name)
}
private func addNewItem() {
withAnimation {
let newItem = ShoppingList.Item(name: newItemName)
shoppingList[index].items.append(newItem)
}
}
}
And of course parent view:
struct ShoppingListsView: View {
@Binding var shoppingLists: [ShoppingList]
var body: some View {
List {
ForEach($shoppingLists) { $list in
NavigationLink(destination: ShoppingListDetailView(shoppingList: $shoppingLists, index: shoppingLists.firstIndex(of: list)!)) {
ShoppingListItemView(shoppingList: $list)
}
}
}
.navigationTitle("Shopping List")
}
}
I'm new to Swift (not to mention SwiftUI) and I have no idea what might be wrong here. Any ideas?