我们常用Foreach来遍历数组生成一个列表视图,SwiftUI为我们提供了非常简单方便的删除方式。在看过其他人发布的代码里经常能看到无法使用数组直接remove的情况,这里介绍一个正确的使用方法。

界面样式

删除列表元素

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import SwiftUI

struct ContentView: View {
@State private var numbers: [NumberInfo] = [
NumberInfo(num: 1, info: false),
NumberInfo(num: 2, info: true),
NumberInfo(num: 3, info: false)
]

var body: some View {
VStack {
Form {
ForEach(numbers, id: \.self) {
Text("\($0.num)")
}
.onDelete(perform: removeRows)

}
}
}

func removeRows(at offsets: IndexSet) {
numbers.remove(atOffsets: offsets)
}
}

struct NumberInfo: Hashable {
var num = 1
var info = false
}

说明

首先我们建立一个结构体,用于作为数据的类型

1
2
3
4
struct NumberInfo {
var num = 0
var info = false
}

然后我们创建一个数组,数组里包含我们需要循环的数据

1
2
3
4
5
@State private var numbers: [NumberInfo] = [
NumberInfo(num: 1, info: false),
NumberInfo(num: 2, info: true),
NumberInfo(num: 3, info: false)
]

之后我们需要构建一个循环,因为我们需要对数据进行变更,所以我们直接遍历数组,而不是去遍历count

1
2
3
4
5
VStack {
ForEach(numbers,id: \.self) { item in
Text("hello")
}
}

这个时候我们会发现报错(结构“ForEach”要求“NumberInfo”符合“Hasable”)

1
Generic struct 'ForEach' requires that 'NumberInfo' conform to 'Hashable'

所以我们需要让NumberInfo符合Hasable协议

1
2
3
4
struct NumberInfo: Hashable {
var num = 0
var info = false
}

之后我们需要添加一个函数,用于处理删除数据。这个函数需要接收一个IndexSet类型的位置标记,用于告诉你应该去删除哪个数据。

使用数组中的<Array>.remove(atOffsets: <IndexSet>)

1
2
3
func removeRows(at offsets: IndexSet) {
numbers.remove(atOffsets: offsets)
}

现在我们只需要在ForEach之后添加修饰

1
.onDelete(perform: removeRows)

就大功告成了!