見出し画像

[SwiftUI]メモアプリに新規メモ機能を追加する Part.3

■初めに


こんにちわ、中川(Twitter)です。

さて、メモアプリの新規メモ機能追加 Part.3です。
今回がラストパートとなります。

前回の記事はこちらから⬇︎

この記事はサンプルアプリのカスタマイズを目的としています。
元となっているサンプルアプリの記事はこちら⬇︎


今回の目標:

◯メモリストのデータをアプリ全体でデータを共有 ⭕️ Part1
◯新規メモ生成用のViewを作成し遷移先に指定 ⭕️
Part2
◯新規メモの追加ロジック作成 ⬅︎ ✅
Part3

使用する主な機能:

1.新規メモデータを配列にinsertする
 
・.insert(at: index)
2. 追加した空メモにメモ詳細を格納
 ・
<配列>[index]["key"] = <プロパティ>
3. 新規メモ作成時点の日付を刻印
 
・Date
 ・DateFormatter
4. 記述のない空メモを自動で消去する

 ・.remove
 ・.onApper

完成図:



[ 🍎 実装開始 🍎 ]

Part.3では、新規メモの作成ロジックを実装します。
追加した新規メモをリスト最前列に持ってくる動き、
メモの内容記述がなかった場合新規メモを自動で削除する動き、
さらに新規メモ作成時点の日付を刻印するコードも実装していきます。

では、実装していきましょう。
よろしくお願いします✊



■新規メモの追加ロジック作成


1.新規メモデータを配列にinsertする


メモのデータは前回作ったViewModel内で管理しています。
管理しているデータ型はDictionary(辞書)型のArray(配列)です。

class MemoData: ObservableObject {

    // 辞書型配列 メモのデータを格納
    @Published var memos = [["memoTitle": " タイトル", "memoTime": "xx月oo日", "memoText": "ここにメモ詳細が記録されます"]]

}
リストに表示されたメモデータ

このデータ内に新規メモ要素を追加します。
iPhone標準搭載のメモだと、
新規メモ追加ボタンを押した時点で、
新規メモViewへの遷移と同時に空のメモデータが
リストに入り込む挙動だったので、
動きをトレースして実装します。

まず、ホーム画面のMemoListViewに
空の辞書型配列プロパティを作成します⬇︎
辞書のkeyがメモデータのkeyと同名かをしっかり確認しましょう。

// 新規メモ作成ボタンをタップするとこのプロパティ内の空メモ要素が配列memosの[0]にインサートされる
    var newMemo = ["memoTitle": "", "memoTime": "", "memoText": ""]

次に、前回作成した新規メモViewへの遷移を紐付けたボタンの
ボタンアクションクロージャ内に新たにコードを追記します。
この部分ですね。

新規メモViewへの遷移ボタン


// 新規メモView遷移ボタン
                Button(action: {

                    // 新規メモデータをメモデータ配列のindex[0](最前列)へ格納
                    vm.memos.insert(newMemo, at: 0)  // ✅
                    isActive.toggle()
                }) {
                    Image(systemName: "square.and.pencil")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 25, height: 25)
                        .padding(.top)
                }

 vm.memos
ViewModel内のメモデータを指しています。

.insert(newMemo, at: 0)
対象データにnewMemo(先ほど作った空のメモデータ)を指定し、
at: 0で配列内の最前列にデータを追加しています。
この数字は配列が保持するindexを表しており、
at: 1なら2番目、at: 4 なら5番目に追加されます。

この記述により、新規メモ遷移ボタンをタップ時に
空の新規メモがリストに追加されます。

見えづらいか🙇‍♂️

…見えますでしょうか?笑
画面遷移の一瞬、リストの最上部に空のリストが追加されているのが確認できればと思います。


2. 追加した空データにメモ詳細を格納


次に、先ほど追加したからデータにメモの内容を
格納できるようにしましょう。
新規メモ画面NewMemoViewを見ていきます。

@StateObject var vm: MemoData
@State var newMemoTitle = ""  // ⬅︎ ①
@State var newMemoText = ""   // ⬅︎ ②

// --------------------------------------------------------

// メモのタイトルを記入するテキストボックス
            TextField("タイトル", text: $newMemoTitle)

// メモ詳細を記入するテキストボックス
            TextEditor(text: $newMemoText)

.navigationBarItems(trailing: Button("完了") {

            vm.memos[0]["memoTitle"] = newMemoTitle  // ✅ ①
            vm.memos[0]["memoText"] = newMemoText    // ✅ ②

            self.presentationMode.wrappedValue.dismiss() // 遷移元へ戻る

        }.padding())

上記のように、vm.memos[0](空のメモ)の追加したいkeyに
テキストvalueを格納します。
これで新規メモViewで記入したテキストが
ボタン遷移時に生成されていた空のメモに格納されます。



3. 新規メモ作成時点の日付を刻印


次に、メモ作成時点での日付をメモに刻印する実装を
していきましょう。
まず、NewMemoViewに新しくプロパティを宣言します。

  // 現在時刻を出力するためのDateインスタンスとDateFormatterインスタンス
    private let date = Date()  // ✅
    private let dateFormatter =  DateFormatter()  // ✅
     @State private var newMemoTitle = ""
     @State private var newMemoText = ""
   // 時刻を保持するStringプロパティ
     @State private var newMemoTime = ""  // ✅

次に、先ほどの完了ボタンの実行クロージャに追記します。

.navigationBarItems(trailing: Button("完了") {  

         // 現在時刻を生成して新規メモのmemoTextに格納
           dateFormatter.dateFormat = "MM月dd日"  // ✅
           newMemoTime = dateFormatter.string(from: date)  // ✅

            vm.memos[0]["memoTitle"] = newMemoTitle
            vm.memos[0]["memoText"] = newMemoText
            vm.memos[0]["memoTime"] = newMemoTime  // ✅

.dateFormat = ""で時刻出力フォーマットの設定をしています。
MMは月(month)、ddは日(day)を意味します。

●dateFomat
年 /  YYYY 
月 / MM 
日 / dd
時 / HH
分 / mm
秒 / ss

準備できたフォーマットをnewMemoTimeに格納して、
vm.memos["memoTime"]のvalueを更新しています。
時刻の実装に関してはこちらの記事が
わかりやすいかと思いいます、参考にどうぞ⬇︎


はい、これで新規メモ作成時点での日付が
出力されるようになりました✊

メモ詳細に日付が刻印


 4. 記述のない空メモを自動で消去する



現在の状態だと、一度空のメモデータを生成すると
メモに記述がなかったとしてもリストにメモが残ってしまいます。

空のメモが残る

新規メモに記述がなければ、削除してしまいましょう。
ホーム画面MemoListViewに戻り、.onApperを実装します。

 // 新規メモView遷移ボタン
                Button(action: {

                    // 新規メモデータをメモデータ配列のindex[0](最前列)へ格納
                    vm.memos.insert(newMemo, at: 0)
                    isActive.toggle()
                }) {
                    Image(systemName: "square.and.pencil")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 25, height: 25)
                        .padding(.top)
                }
            } // VStack
             //メモリスト表示時に、タイトルと詳細が空の新規メモが存在していた場合、自動で削除  // ✅
            .onAppear() {
                if vm.memos[0]["memoTitle"] == "" && vm.memos[0]["memoText"] == "" {
                    print("メモが空白だったので削除しました")
                    vm.memos.remove(at: 0)
                }
            }

.onApperは、対象のView表示時に実行される処理です。
新規メモ作成Viewから遷移元に戻ってきた時に、
空のメモに内容が追加されていなかった場合、
生成した空のメモデータを.remove(at: 0)で削除します。


はい!これで目標機能の実装が完了です。
お疲れ様でした◎

■まとめ


はい!以上、メモサンプルアプリ全3Partにかけて
お送りしました。
いかがだったでしょうか?
もし何か質問や気づいたことなどあれば、
ぜひコメントいただけると幸いです🙏

追加したメモの内容編集機能も作ろうとしたのですが、
少し詰まってしまったので、
また実装出来次第ここに書いていければと思います。

ここまで読んでいただきありがとうございました!

ではでは🙌

[一緒に読んでほしい記事]



◆メモサンプルアプリ作成 

◆メモアプリ機能カスタマイズPart1 

◆メモアプリ機能カスタマイズPart2

Thank you!!😸



この記事が気に入ったらサポートをしてみませんか?