I have the following reproduced example in Swift/SwiftUI.
Intended Functionality: List of numbers, where upon deletion of any number, the numbers update and reorganize so that they are in consecutive order.
Example: Suppose we have numbers 1, 2, 3, 4 in a list. When we delete number 2, the list should become 1, 2, 3 instead of staying like 1, 3, 4.
Problem: When @State
is used to hold the array of numbers, the code works as expected. However, when an array in @AppStorage
is used to hold the array, the view does not seem to update/change the numbers.
So, why can't I use the @AppStorage
approach, and how can I fix this?
I know the code looks like a lot, but you can mostly ignore it if you just read the comments. It's just a body with a couple of functions, nothing crazy.
class MyObj: Codable, Identifiable { //SIMPLE OBJECT TO HOLD A NUMBER
init(num: Int) {
self.num = num
}
var id: UUID = UUID()
var num: Int
}
struct test2: View {
@State var array: [MyObj] = [] //USING THIS (@State) WORKS
//AppStorage("array") var array: [MyObj] = [] //USING THIS (@AppStorage) DOESN’T UPDATE NUMBERS
func minimizeNums() {
for i in 0..<array.count { //MAKES NUMBERS IN ORDER/CONSECUTIVE
array[i].num = i
}
}
var body: some View {
VStack {
Button("add number object") {
array.append(MyObj(num: array.count))
}
List {
ForEach(array) { obj in
Text(String(obj.num))
}
.onDelete(perform: { index in
array.remove(atOffsets: index) //REMOVES NUMBER OBJECT FROM LIST
minimizeNums() //MAKES THE REMAINING OBJECT'S NUMBERS CONSECUTIVE
})
}
}
}
}
Important: I used the extension from this accepted answer in order to store arrays in @AppStorage
. I assume this extension may be contributing to the problem, but I'm not sure how!
CodePudding user response:
This is failing, because you are using a class for your model MyObj
. There are multiple reasons for using structs with SwiftUI
. Please read Blog entry or any other tutorial or documentation.
[TLDR]: Don´t use classes use structs.
Changing MyObj
to:
struct MyObj: Codable, Identifiable {
init(num: Int) {
self.num = num
}
var id: UUID = UUID()
var num: Int
}
should work.