[SwiftUI][CoreData] SwiftUI と MVVM で始める CoreData 入門 (その10:Ver.2 で Priority を導入)

SwiftUI と CoreData を組み合わせたアプリの作り方を説明します。

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Catalina 10.15.7
  • Xcode 12.3
  • iOS 14.2

Ver.2 として機能追加

以下の機能追加をしていきます。

  • TODOItem が、優先度を持つ
  • 優先度でソート可能にする
  • UNDO/REDO 対応?

Model(TODOItem/CDTODOItem, TODOItemStore) へ機能追加

TODOItem, TODOItemStore のテスト追加

モデル等のファイルを変更する前に、テストを作成します。

以下のテストを追加します。

  • 設定した priority が保存されているか
Model_Tests.swift テスト修正
コード解説
  1. initializer に priority を指定できるようにします
  2. 設定した priority が取得できることをテスト

テストができたので、モデルに優先度(priority)を追加します。

CoreData モデルのバージョン追加

CoreData のモデルから、変更していきます。

既存のモデルを変更してしまうと、以前のモデルを読み込めなくなってしまいます。

新しい Version のモデルとして作成すれば、以前のモデルから migration することが可能となります。

新しい Version 設定

CoreData のモデルに新しい Version を設定します。以下の手順です。

  1. Xcode で モデルファイル(MyTODO.xcdatamodeld) を開く
  2. メニュー [Editor]-[Add Model Version…] を選択する
  3. Version name を設定する(ver2 としました)
Add Model Version...
Add Model Version…

新しい Version にプロパティ追加

Xcode の Project Navigator で CoreData ファイルを見ると、複数のファイルを内包するように変わっています。

先ほど作成した ver2 を選択して、新しいプロパティを追加していきます。

モデル ver2
モデル ver2 を選択

プライオリティ(Int型) を追加します。

プライオリティ追加
プライオリティ追加

作成後に、Current を、現在作った ver2 に設定します。

ModelVersion の設定
ModelVersion の設定
ModelVersionの設定

これで、CoreData 側は OK です。

TODOItem, TODOItemStore の実装追加

次に、TODOItem に dueDate に対応するプロパティを追加します。
initializer 等も全て修正します。

TODOItem

コード解説
  1. Priority を保存するプロパティを定義
  2. init の引数に priority を追加
  3. Priority は enum で定義 (CoreData で保存に使用する Int16 での initializer も定義)

上記以外にも、以下の箇所の修正が必要となります。

  • CoreData Entity からの TODOItem 生成メソッド(TODOItem.init(_ cdItme:CDTODOItem))
  • 新規 TODOItem 作成メソッド(TODOItemStore.createTODOItem)
  • 新規 TODOItem 作成メソッド(MyTODOViewModel.createTODOItem)

上記のコードで先ほど作ったモデルのテストはパスします。過去のモデルテストもパスすることを確認して、View/ViewModel に着手します。

View(MyTODOMainView) への機能追加

機能追加としては、以下の点になります。

  • TODOItem 表示に、プライオリティ表示を追加
  • 編集画面に、プライオリティを表示し変更可能に

View の修正での必要に応じて、ViewModel も変更していきます。

View のテスト追加

PageObject 的には、新しく表示される締切日を 処理するためにTODOItemRowPageObject を修正したいのですが、NavigationLink を使う関係で、表示要素の詳細を取得することが難しいので、編集画面でテストすることにします。

つまり、PageObject 的には、TODOListItemDetailPageObject のみを対応させます。

編集画面でのプライオリティ選択は、Segmented Control にします。

プライオリティ選択の要素も考慮した PageObject は、以下のようになります。

TODOListItemDetailPageObject
コード解説
  1. SegmentedControl の各要素へアクセスできるようにします
  2. プライオリティを設定するメソッドを用意
  3. 選択されているプライオリティを返すメソッドを用意

View のテストを追加

ビューテストの準備ができましたので、ビューのテストを作成します。これまでのテストにプライオリティ操作を追加しています。

Viewテスト

コード解説
  1. TODOItem 編集時に、プライオリティを low に設定します
  2. 改めて詳細画面に行った時に、low が選択されていることをテストします

View の実装

以下の箇所に、due date を表示するように変更します。

  • MainView のリストの行に 追加表示
  • TODOItem の編集ビューに 追加表示

MainViewのリストの行に追加表示します。(現状では、テスト対象外です)

TODOItemView

コード解説
  1. プライオリティに応じて使用するイメージの情報を viewModel から取得します
  2. 取得した情報を使って、プライオリティに応じたイメージを表示します

ViewModel に以下のメソッドを追加して、プライオリティに応じたイメージを作れる情報を返します。

priorityImageInfoForItem

プライオリティのアイコンは、それぞれ以下のようにしました。

プライオリティアイコン
プライオリティアイコン

次に、TODOItem の詳細を表示するビューにも追加します。

詳細ビュー(編集ビュー)は、プライオリティを表示するために、Picker を追加しました。

example

コード解説
  1. 編集時には、プライオリティも編集対象として、editItem に値を保存します
  2. プライオリティを表示する Picker です
  3. 作成/編集終了時に、プライオリティも反映します

上記の修正を行うと、これまでのテスト全てをパスすることを確認できます。

これまで通りテストを行いました。

今回は、CoreData モデルに新しいバージョンを設定して変更を加えましたので、過去バージョンからの移行として以下を行うようにしてみます。

  • 過去バージョンからのマイグレーション設定
  • 過去バージョンからのマイグレーションのテスト

続きは次回です。

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です