今回はListの機能の一つである、セルの選択方法について説明します。
環境
- Xcode12.5.1
- iOS14.6
- スクショはiPhone12Pro Maxで撮影
初めに
条件は前回の記事【SwiftUI】Listの機能 – 行の並べ替え、削除 と同じです。
Listの基本的な実装方法は本記事では説明しません。とは言えコードは記載しますし、List自体は非常に簡単に実装できると思います。
また、ListとForEachで一覧表示を実装していること、ForEachでは更新可能な配列を使用しておりidを用いて識別されることが前提となります。
今回説明に使用するコードはこちらです。Personは必ずHashableに準拠するようにしてください。理由については今度詳しく説明します。
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
var body: some View {
VStack {
List {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
}
}
}
selectionを使う前に
selectionを使う前に、Listを編集可能な状態にするための準備が必要です。方法は2つあります。
1つは環境値.environmentを使って編集状態にする方法。
もう1つはEditButton()を設置する方法です。
.environmentを使った方法
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
var body: some View {
VStack {
List {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
.environment(\.editMode, .constant(.active))
}
}
}Listのモディファイアとして.environment(.editMode, .constant(.active))をつけてあげるだけです。こうするとListは常に編集可能な状態になります。
EditButton()を設置する方法
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
var body: some View {
VStack {
EditButton()
List {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
}
}
}レイアウトのどこかにEditButton()を置くだけです。こうするとボタンが表示され、そのボタンをタップするとListを編集可能な状態になります。
selectionを使った単体選択
まずは、選択したセルの情報を保持する変数selectedValueを用意します。今回はPerson型のデータをForEachで回して表示しているので、保持する変数もPerson型にします。このForEachで回すデータの型と選択したデータを保持する変数の型が一致していないと正しく動作しないので気をつけてください。
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
@State private var selectedValue: Person?
var body: some View {
VStack {
List {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
.environment(\.editMode, .constant(.active))
}
}
}次に、Listのイニシャライザでselectionを指定します。引数には上で用意した変数selectedValueを設定します。
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
@State private var selectedValue: Person?
var body: some View {
VStack {
List(selection: $selectedValue) {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
.environment(\.editMode, .constant(.active))
}
}
}こうするだけでリストの左側に選択マークが表示され、セルの選択が可能になります。


これで選択したデータはselectedValueに渡されるので、selectedValueを使って色々と処理ができます。例として、選択中のデータのnameを表示するようにしてみましょう。VStack の中に Text("選択:\(selectedValue?.name ?? "")")を追加します。
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
@State private var selectedValue: Person?
var body: some View {
VStack {
Text("選択:\(selectedValue?.name ?? "")")
List(selection: $selectedValue) {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
.environment(\.editMode, .constant(.active))
}
}
}
選択したデータのnameが表示されるようになりました。
複数選択する方法
複数選択する場合は、selectedValueをSet<>型にする必要があります。
Set<>型とは配列のようなもので、ユニークなデータしか保持しないため、同じデータを追加しようとしても追加されない特徴があります。また、データの順番という概念もありません。
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
@State private var selectedValue: Set<Person> = []
var body: some View {
VStack {
Text("\(selectedValue.count)")
List(selection: $selectedValue) {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
.environment(\.editMode, .constant(.active))
}
}
}このようにselectedValueをSet<Person>という型にすることで、複数選択が可能になります。

今回は以上です。UIKitのUITableViewに比べて非常にシンプルな実装になりましたよね。


コメント