作成中です。
このPartでは、リストを使ってなんちゃってToDoリストを作ってみます。
では実装していきましょう。ToDoListという名前でプロジェクトを作成してください。
レイアウト実装
まずは、レイアウトを作っていきましょう。
まずは、ナビゲーションバーを作りましょう。以下のように変更してください。
var body: some View {
NavigationView {
Text("Hello, world!")
.padding()
.navigationTitle("ToDoリスト")
}
}

次にリストを作りましょう。
NavigationView {
List {
Text("ジョギングする")
Text("お花に水をやる")
Text("部屋の掃除をする")
Text("本を読む")
}
.navigationTitle("ToDoリスト")
}


実行するとこのようなレイアウトになります。
一つ一つHStackで囲んで、Imageをつけましょう。
NavigationView {
List {
HStack {
Image(systemName: "circle")
Text("ジョギングする")
}
HStack {
Image(systemName: "checkmark.circle.fill")
Text("お花に水をやる")
}
HStack {
Image(systemName: "checkmark.circle.fill")
Text("部屋の掃除をする")
}
HStack {
Image(systemName: "circle")
Text("本を読む")
}
}
.navigationTitle("ToDoリスト")
}


このような見た目になるはずです。
これで見た目はいい感じになりました。
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
List {
HStack {
Image(systemName: "circle")
Text("ジョギングする")
}
HStack {
Image(systemName: "checkmark.circle.fill")
Text("お花に水をやる")
}
HStack {
Image(systemName: "checkmark.circle.fill")
Text("部屋の掃除をする")
}
HStack {
Image(systemName: "circle")
Text("本を読む")
}
}
.navigationTitle("ToDoリスト")
}
}
}
ForEachで書く
現時点では、Listの中に、4回目もHStackを書いています。ですが、なるべく同じような処理はひとまとまりにした方が綺麗です。
ということで、何回も書いているHStackをまとめましょう。
まずは、データを配列で持ちましょう。
let taskData = ["ジョギングする", "お花に水をやる", "部屋の掃除をする", "本を読む"]

Listの中を以下のように変更してください。これでだいぶコードが短くなります。
List(0..<taskData.count, id:\.self) { index in
HStack {
Image(systemName: "circle")
Text(taskData[index])
}
}


実行して確認してみてください。アイコンは◯だけになっちゃいますが、先ほどと同じレイアウトになるはずです。
List(0..<taskData.count, id:\.self) { index in
List()の中に、0..<5と書くと、中の処理が5回繰り返されセルが5つ表示されます。
今回は、taskDataの数だけ表示したいので、0..<taskData.countというふうにしています。taskDataは、4個あるので、実質0..<4と書いているのと同じです。
indexはなんなのかというと、繰り返している回数が入ります。繰り返し1回目はindexが1で実行されます。2回目はindexが2で実行されます。というふに現時点の繰り返しの回数が入ります。
Text(taskData[index])
taskData[0]で"ジョギングする"が取得できます。taskData[1]だと、"お花に水をやる"が取得できます。というふうに、taskData[]の中に番号を入れることで、値を取得できます。
今回は、そこにindexを入れることで、すべてのデータを表示させています。
これで、コードが少なくなり、わかりやすいコードになりました。
import SwiftUI
struct ContentView: View {
let taskData = ["ジョギングする", "お花に水をやる", "部屋の掃除をする", "本を読む"]
var body: some View {
NavigationView {
List(0..<taskData.count, id:\.self) { index in
HStack {
Image(systemName: "circle")
Text(taskData[index])
}
}
.navigationTitle("ToDoリスト")
}
}
}
機能をつける
では、ToDoリストっぽく、ボタンを押したらチェックマークがつくようにしましょう。
まずは、セルを押せるようにしましょう。以下のようにHStackをButtonの中に入れましょう。
Button(action: {
print("セルが押されたよ")
}) {
HStack {
Image(systemName: "circle")
Text(taskData[index])
}
}


このようにセルを押せるようになってるはずです。
Buttonにしたら文字色が青になってしまったので、以下のモディファイアをつけて黒に戻します。
Button(action: {
print("セルが押されたよ")
}) {
HStack {
Image(systemName: "circle")
Text(taskData[index])
}
}
.foregroundColor(.black)


黒に戻りました。
現状のデータは、タスクが終了しているかどうかの値がないため、ボタンを押したらチェックマークがつくという実装ができません。なので、データの構成を変更します。
クラス外に以下のモデルを追加してください。
struct TaskData: Identifiable {
var title: String
var completed: Bool
var id = UUID()
}

taskDataを以下のように変更してください。(現時点ではエラーになります。)
@State var taskData = [
TaskData(title: "ジョギングする", completed: false),
TaskData(title: "お花に水をやる", completed: false),
TaskData(title: "部屋の掃除をする", completed: false),
TaskData(title: "本を読む", completed: false)
]

データを変更したので、Text(taskData[index])のところでエラーになっています。以下のように変更してください。
HStack {
Image(systemName: "circle")
Text(taskData[index].title)
}

もし、completedがfalseだったら◯で、trueだったら☑️にしましょう。Imageの部分を以下のように変更してください。
if taskData[index].completed {
Image(systemName: "checkmark.circle.fill")
} else {
Image(systemName: "circle")
}

このくらいのif文なら、三項演算子を使った方が良いです。Imageのif文を以下のように変更しましょう。
Image(systemName: taskData[index].completed ? "checkmark.circle.fill" : "circle")

ボタンを押したら、completedの値を変更するようにしましょう。
Button(action: {
print("セルが押されたよ")
taskData[index].completed.toggle()
}) {


セルを押すとチェックマークがついてもう一度押すとチェクマークが外れるようになると思います。
Bool型に.toggle()とつけると、値が逆になります。つまり、falseだったらtrueになり、trueだったらfalseになります。
これで、なんちゃってToDoが完成しました!
ここから、ToDoの入力フォームを作って、データを保存できるようにすれば本格的なToDoになると思います!
import SwiftUI
struct TaskData: Identifiable {
var title: String
var completed: Bool
var id = UUID()
}
struct ContentView: View {
@State var taskData = [
TaskData(title: "ジョギングする", completed: false),
TaskData(title: "お花に水をやる", completed: false),
TaskData(title: "部屋の掃除をする", completed: false),
TaskData(title: "本を読む", completed: false)
]
var body: some View {
NavigationView {
List(0..<taskData.count, id:\.self) { index in
Button(action: {
print("セルが押されたよ")
taskData[index].completed.toggle()
}) {
HStack {
Image(systemName: taskData[index].completed ? "checkmark.circle.fill" : "circle")
Text(taskData[index].title)
}
}
.foregroundColor(.black)
}
.navigationTitle("ToDoリスト")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

