I was puzzled by the crash when removing an added item.
That had to do with the focus on the TextField…
This works more properly:
struct FileItem: Identifiable {
var name: String
var children: [FileItem]? // 👈🏻 Will be nil if child at lowest level of hierarchy ; otherwise for parent, should be [] when no child
var id: String { name }
}
struct ContentView: View {
@State var data: [FileItem] = [
FileItem(name: "First", children: [FileItem(name: "childF1"), FileItem(name: "childF2")]),
FileItem(name: "Second", children: [FileItem(name: "childS1"), FileItem(name: "childS2"), FileItem(name: "childS3")]),
FileItem(name: "Third", children: [FileItem(name: "childT1"), FileItem(name: "childT2")])
]
@FocusState private var focusedField: String?
var body: some View {
List($data, children: \.children) { $item in
HStack {
TextField("", text: $item.name) // probleme : le clavier disparait à chaque caractère
// Avec focused, on passe au dernier TextField
.focused($focusedField, equals: item.name)
.task {
self.focusedField = item.name
}
// If there are no children, we cannot remove it
if item.children != nil { // So it is parent, maybe with no child []
Spacer()
Button("Add child") {
// let's search its position in data
for (index, parent) in data.enumerated() {
if parent.name == item.name && parent.children != nil { // double check on nil
let childrenCount = parent.children!.count
var newChildName = "new child \(childrenCount+1)"
for child in parent.children! { // let's not give the same name twice
if newChildName == child.name {
newChildName = "new child \(childrenCount+100)"
}
}
data[index].children!.append(FileItem(name: newChildName))
}
}
}
.foregroundColor(.green)
.buttonStyle(.borderless)
}
Spacer()
Button("Remove") {
// This is a simple implementation if only children, no grandChildren
// if grandchildren, need to have a recursive search for the parent
self.focusedField = nil
var deleteDone = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { // <<-- To give time to update focus
for (index, individual) in data.enumerated() {
// remove child
if deleteDone { print("I quit loop") ; break }
if !deleteDone {
if individual.children != nil && !individual.children!.isEmpty {
for child in individual.children! {
if child.name == item.name {
var newChildren = individual.children!
newChildren.removeAll(where: { $0.name == item.name })
data[index].children = newChildren
deleteDone = true
break
}
}
}
// remove parent
if !deleteDone {
for (index, individual) in data.enumerated() {
if individual.name == item.name {
data.remove(at: index)
deleteDone = true
break
}
}
}
}
}
}
.foregroundColor(.red)
.buttonStyle(.borderless)
}
}
}
}