【Swift】Core Dataの使い方。Fetch Requestをモデルに定義する。(Swift 2.1、XCode 7.2)
Fetch Requestをモデルに定義するとは
本記事ではFetch Request(以下、フェッチリクエスト)をモデルに定義して使う方法を説明する。
前回記事までは、フェッチリクエストの条件式は以下のコードのようにソースコードに直接記述していた。
1 2 3 4 5 6 7 8 9 |
//フェッチリクエストを作成する。 let fetchRequest = NSFetchRequest(entityName: "Book") //フェッチリクエストに条件式を追加する。 fetchRequest.predicate = NSPredicate(format: "name = ’杉田真' AND age > 20’") //フェッチリクエストを実行する。 let result = try managedContext.executeFetchRequest(fetchRequest) as? [Book] |
コードの中で似たような条件式のフェッチを複数箇所で実行する場合、条件式つきのフェッチリクエストをモデルに定義しておくとメンテしやすくなる。
実際にフェッチリクエストをモデルに定義してみよう。
以降の手順を行う前のXcodeプロジェクトをGitHubに置いたので、試してみる人はご利用されたし。
⇒「テスト用プロジェクト」
事前準備では、サーチバーに入力した文字列と一致するデータをフェッチしてテーブルビューに表示するまでを実装しておいた。
以下のコードは、変更前の「検索ボタン押下時の呼び出しメソッド」
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
//検索ボタン押下時の呼び出しメソッド func searchBarSearchButtonClicked(searchBar: UISearchBar) { //キーボードをしまう。 testSearchBar.endEditing(true) //検索結果配列を空にする。 searchResult.removeAll() //フェッチリクエストのインスタンスを生成する。 let fetchRequest = NSFetchRequest(entityName: "Book") if(testSearchBar.text != "") { //属性nameが検索文字列と一致するデータをフェッチ対象にする。 fetchRequest.predicate = NSPredicate(format:"name = %@", testSearchBar.text!) } do { //フェッチリクエストを実行する。 searchResult = try managedContext.executeFetchRequest(fetchRequest) as! [Book] } catch { print(error) } //テーブルを再読み込みする。 testTableView.reloadData() } |
フェッチリクエストをモデルに追加する
下図赤枠の「プロジェクト名.xcdatamodeld」を選択してデータモデルを表示する。黄緑枠の「+」ボタンを長押しして吹き出しのメニューを表示させ、「Add Fetch Request」を選択する。
フェッチリクエストの条件式を追加する
続いて、下図紫枠のデータモデルインスペクタボタンを押して設定画面を表示し、Nameに「TestFetchRequest」を入力する。これはソースコードからフェッチリクエストにアクセスするための識別子である。
赤枠の「+」ボタンを押して行を追加し、黄緑枠の選択ボックスから「Expression」を選択する。Expressionの右側のテキストボックスに「name == $BOOK_NAME」を入力する。これは、フェッチリクエストの条件式である。
ソースコードでフェッチリクエストを取得する
ViewController.swiftの「検索ボタン押下時の呼び出しメソッド」を以下のコードに変更する。
サーチバーに文字が入力されていたら、モデルに定義されているフェッチリクエストを取得している。そのとき、$BOOK_NAMEをサーチバーの文字列に置換するための引数を与えている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
//検索ボタン押下時の呼び出しメソッド func searchBarSearchButtonClicked(searchBar: UISearchBar) { //キーボードをしまう。 testSearchBar.endEditing(true) //検索結果配列を空にする。 searchResult.removeAll() //フェッチリクエストのインスタンスを生成する。 var fetchRequest = NSFetchRequest(entityName: "Book") if(testSearchBar.text != "") { //モデルに定義したフェッチリクエストを取得する。 let applicationDelegate = UIApplication.sharedApplication().delegate as! AppDelegate fetchRequest = applicationDelegate.managedObjectModel.fetchRequestFromTemplateWithName("TestFetchRequest", substitutionVariables: ["BOOK_NAME":testSearchBar.text!])! } do { //フェッチリクエストを実行する。 searchResult = try managedContext.executeFetchRequest(fetchRequest) as! [Book] } catch { print(error) } //テーブルを再読み込みする。 testTableView.reloadData() } |
以下は実際のプレイ動画
上記のように、実行時に条件式を変更するような場合は「Expression」を選択して条件式を記述すること。下図のように、属性名を指定して条件式を作るとキーワードは置換されないので注意すること(Swift 2.1、XCode 7.2)。
ちなみに、実行時に条件式の一部を置換する必要が無い場合は以下のメソッドを用いる。
1 2 3 |
//フェッチリクエストを取得する。 fetchRequest = applicationDelegate.managedObjectModel.fetchRequestTemplateForName("TestFetchRequest")! |
フェッチリクエストの設定項目
フェッチリクエストの設定項目を詳しく見てみよう。
①Fetch all ◯◯ object where:
◯◯にフェッチ先のエンティティを指定する。
② ◯◯ of the following are true
◯◯を以下の3つから選択する。
定数 | 説明 |
---|---|
None | 以下に続く条件に1つも適合しないオブジェクトをフェッチする。 |
All | 以下に続く条件すべてに適合するオブジェクトをフェッチする。 |
Any | 以下に続く条件のどれか1つでも適合するオブジェクトをフェッチする。 |
③ 条件式
Expressionを選択した場合は、右側のテキストボックスに条件式をすべて入力する。
属性名を選択した場合は、右側の選択ボックスから条件を選択、テキストボックスに値を入力する。「数値や日付」と「文字列」の場合で指定できる条件が異なる。
数値や日付の条件
定数 | 説明 |
---|---|
is | 右と等しい |
is not | 右と等しくない |
is less than | 右より小さい |
is greater than | 右より大きい |
is less than or equal to | 右より小さい、または、等しい |
is greater than or equal to | 右より大きい、または、等しい |
文字列の条件
定数 | 説明 |
---|---|
contains | 右を含む |
is | 右と等しい |
is not | 右と等しく無い |
begins with | 右と同じ文字列で始まる |
ends with | 右と同じ文字列で終わる |
④ 表示切り替え
ボタンを押すと、定義した条件式が1文になって表示される。最終確認に使おう。