~~ToDo_of_swift~~

Back to Top

links




アプリ概要

今回はとりあえず何か形あるものを作りたいと思い、ToDoリストの作成に取り組みました。 Swiftの予備知識がなくても、簡単に作成できると思います。

機能紹介

ここでは機能の紹介をしたいと思います。まずは起動直後の画面です。

レイアウトは至ってシンプルです。 上部左右にそれぞれ「削除」「追加」ボタンがあり、そこから、リストの追加や 削除を行います。

次に「追加」ボタン押下時の画面です。

この画面では、ToDoリストへタスクの追加を行います。 今回のデモ画像では、「洗濯」とありますが、そのテキストボックス内に 登録したいタスクを入力し、確定ボタンを押下することで、タスクが登録され、 自動でトップ画面へと戻ります。 また、空白での登録を受け付けず、タスクが必ず入力されていることを保証します。 さらに、タスクの登録を中断したい場合は左上の「<」ボタンを押下することで 登録作業を中断し、トップ画面に戻ることができます。

実際に確定ボタンを押下すると次の画像の様に、登録されたタスクが表示された トップ画面が表示されます。

追加できました!!
他のタスクも追加してみましょう。

ここで、気がついた方もいると思いますが、タスクの左側に丸がありますね。
この丸はチェックリストになっており、タスク終了時にそのタスクを押下することで 終了の印のチェックがつきます。 実際に押下してみると...

このようにチェックがつきます。
チェックがついた状態で左上の「削除」ボタンを押下すると...

この様に、チェックしていたタスクが削除されました。
以上がこのToDoアプリの機能になります。簡単な構造ですが、ToDoリストに必要な 最低限のものは実現できました。

コード(全体)

以下がコードの全体像になります。

/ContentView


import SwiftUI

struct TaskData{
    var title:String
    var completed:Bool
    var id = UUID()
}

struct ContentView: View {
    
    @State var appendTask:Bool = false
    @State var taskList:Array = []
    @State var task:String = ""
    @State var rowCnt:Int = 0
    
    var body: some View {
        if self.appendTask {
            NavigationView{
                List{
                    TextField("タスクを入力してください", text: $task)
                    
                    HStack{
                        Spacer()
                        Button(action: {
                            print("確定")
                            if task != ""{
                                taskList.append(TaskData(title: task, completed: false))
                                task = ""
                                appendTask.toggle()
                            }
                        }){
                            Text("確定")
                        }.foregroundColor(Color.blue)
                        Spacer()
                        
                    }
                    
                }.navigationTitle("追加")
                    .navigationBarItems(leading: Button(action: {
//                        print("戻る")
                        appendTask.toggle()
                    }){
                        Image(systemName: "lessthan")
                    })
            }
        }else{
            NavigationView{
                VStack{
                    List(0..<taskList.count, id:\.self){ index in
                        Button(action:{
//                            print("ボタンが押されたよ")
                            
                            taskList[index].completed.toggle()
                        }){
                            HStack{
                                Image(systemName:taskList[index].completed ? "checkmark.circle.fill" : "circle")
                                Text(taskList[index].title)
                            }
                        }.foregroundColor(.black)
                    }.navigationTitle("ToDoリスト")
                        .navigationBarItems(leading: Button(action: {
                            self.rowCnt = taskList.count
                            for i in 0..<taskList.count{
                                print((self.rowCnt - 1) - i)
                                if taskList[(self.rowCnt - 1) - i].completed{
                                    taskList.remove(at: (self.rowCnt - 1) - i)
                                }
                                
                            }
                        }){
                            Text("削除")
                        }, trailing: Button(action: {
                            appendTask.toggle()
                        }){
                            Text("追加")
                        })
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
        }
    }
}                    
                

コード解説

ここでは、今回コードを作成するにあたって重要だと思った部分を抜粋して 解説します。

タスクの管理

タスクの管理は以下の様な構造体で管理しています。

変数の役割としては

title: タスク名
completed: 終了判定
id: 一意のID

といった感じです。Bool型のcompletedはチェックマークの表示に使用しています。 タスク作成時はfalseですが、押下することで、trueとなりチェックマークがつきます。 また、true時に押下するとチェックマークがはずれ、falseへと戻ります。

そのほかに用意した変数

そのほかに用意した変数としては以下のものが挙げられます。

変数の前に「@State」とついていますね。
これは、現時点での自分なりの解釈となってしまいますが、その変数の状態を 監視しているといった雰囲気です。
変数の状態の変化を認識してくれるので、今回は画面遷移に使用しました。
それでは、それぞれの変数についての説明です。

appendTask: 画面遷移用
taskList: 登録したタスクを管理するための配列
task: タスクのタイトルを保持するための変数
rowCnt: 現在登録されているタスクをカウントするための変数

といった内容になっています。

画面遷移はどうなってるの

画面遷移はどうなっているのでしょうか。
先ほどの変数の説明で、画面遷移用の変数「appendTask」がありました。 この変数とif文を組み合わせることで画面遷移をおこなっています。 プログラムを大きく分割してみてみましょう。

この2つのブロックはよくみるとif文によって分けられています。 コードを省力してみてみると...


if self.appendTask{
    // タスク追加用画面
}else{
    // Top画面
}
                

この様に、appendTaskがtrueの時は、タスク追加用画面が、 falseの時はTop画面が表示される様になっています。また、これらの条件分岐は 「@Status」により、appendTaskの値が変更されるたびに実行されます。

こだわりポイント

今回こだわった部分は、空白でのタスク追加を受け付けない機能です。

26~31行目のプログラムですが、task変数を使用することで、入力があったときのみ、配列へ追加し、 追加が終わった後には「""」によって初期化をおこなっています。単純な処理ですが、ToDoリストに おいてとても大事な処理だと思いました。

まとめ

簡単なプログラムで、比較的できの良いToDoリストが作成できたので、 アプリ作成の第一歩として楽しく作成できました。一方で、より実践的な開発手法や コーディングなど、基礎の知識では補えない部分があるので、あまり綺麗なアプリの作り方では ないのかなと思いました。また、改善点も多くあり、具体的には、アプリのタスクを切った時に 登録していたリストを保持することができず、初期化されてしまうバグがあります。このバグは、 端末自体にデータを保持するか、サーバで管理することで解決できるのではないかと考察しています。 今回のアプリ作成をきっかけに、設計手法やデータの保存方法など、コーディング以外の部分も学習 していこうと思いました。


《参考文献》
Listを使ってToDoリストを作ってみよう!
https://ios-docs.dev/swiftui-part10/

さまざまなSwiftUIの画面遷移について
https://yosshiblog.jp/swiftui_screen-transiton/