【Swift】Core Dataの使い方。フェッチの件数制限、並び替え、開始位置を指定する。(Swift 2.1、XCode 7.2)
NSFetchRequestの続き
本記事は、前回記事「フェッチリクエストで取得するデータを絞り込む」の続きである。
前回記事ではフェッチリクエスト実行時に絞り込み条件を指定する方法を説明した。本記事では、その他の指定できるものを紹介する。
フェッチ件数を制限する(fetchLimitプロパティ)
指定した件数以上フェッチできないようにする。
例えば、fetchLimitプロパティに2を設定してフェッチリクエストを実行したとき、3件以上のデータがヒットしたとしても2件だけフェッチされるということだ。
実際に試してみよう。
ViewController.swiftの「検索ボタン押下時の呼び出しメソッド」を以下のコードに変更する。フェッチリクエスト実行前にfetchLimitプロパティに2を設定している。
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 32 33 |
//検索ボタン押下時の呼び出しメソッド func searchBarSearchButtonClicked(searchBar: UISearchBar) { //キーボードをしまう。 testSearchBar.endEditing(true) //検索結果配列を空にする。 searchResult.removeAll() //フェッチリクエストのインスタンスを生成する。 let fetchRequest = NSFetchRequest(entityName: "Book") if(testSearchBar.text != "") { //属性nameに検索文字列を含むデータをフェッチ対象にする。 fetchRequest.predicate = NSPredicate(format:"name CONTAINS %@", testSearchBar.text!) } //フェッチ件数を2件に制限する。 fetchRequest.fetchLimit = 2 do { //フェッチリクエストを実行する。 searchResult = try managedContext.executeFetchRequest(fetchRequest) as! [Book] } catch { print(error) } //テーブルを再読み込みする。 testTableView.reloadData() } |
以下は実際のプレイ動画。
並び順を指定する(sortDescriptorsプロパティ)
属性とソート順(昇順、降順)を指定してフェッチ結果を並び替える。
以下のコードのように、keyには並び替えの基準となる属性名を指定する。ascendingがtrueの場合は昇順、falseの場合は降順になる。
1 2 |
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "price", ascending: false)] |
複数の属性を指定できる。以下のコードではprice、publisherの優先順序で並び替えが実施される。
1 2 3 |
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "price", ascending: false), NSSortDescriptor(key: "publisher", ascending: false)] |
大文字、小文字を区別しない
並び替えの比較方法を変更するには、第3引数に比較オプションを設定する。
例えば、A,a,B,b,C,cを並び替える場合、比較オプションを指定しない場合は以下のように大文字と小文字が別のものとして並び替えられるが、
B
C
a
b
c
以下コードの比較オプションを与えると、
1 2 3 4 5 6 |
//大文字、小文字を区別しない比較オプション fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true, selector: "caseInsensitiveCompare:")] //ローカライズした上で大文字、小文字を区別しない比較オプション fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true, selector: "localizedCaseInsensitiveCompare:")] |
大文字、小文字を区別せずに並び替えが行われる。
a
B
b
C
c
Finderの表示順に並び替える
文字列の1,2,3,11,22,33を並び替える場合、比較オプションを指定しない場合は以下のように先頭1⇒先頭2⇒先頭3の順番で並ぶが、
11
2
22
3
33
以下コードの比較オプションを与えると、
1 2 3 |
//Finderと同じ表示順に並べる比較オプション fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true, selector: "localizedStandardCompare:")] |
数字の順番に並ぶ。⇒「文字列操作プログラミングガイド(公式DOC)」
2
3
11
22
33
フェッチ開始位置を指定する(fetchOffsetプロパティ)
指定されたインデックス番号から後ろのデータをフェッチする。並び替えを行った場合は、並び替え後のインデックス番号の位置から後ろのデータが取得される。
では、検証データを以下に変更し、フェッチ開始位置を2、フェッチ件数を5件、比較オプションを「Finderの表示順」にして実行してみよう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
//検証用データ let dataList = [["NO1 月刊コロコロコミック", "小学館",390,20.2,"2016/5/16 10:30:00"], ["NO9 コロコロイチバン!","小学館",540,25.3,"2016/4/23 09:00:00"], ["NO2 最強ジャンプ","集英社",420,13.2,"2016/6/9 7:00:00"], ["NO10 Vジャンプ","集英社",300,13.4,"2016/1/3 12:00:00"], ["NO3 週刊少年サンデー","小学館",280,16.7,"2016/8/23 11:00:00"], ["NO11 週刊少年マガジン","講談社",250,40.5,"2016/10/10 7:30:00"], ["NO4 週刊少年ジャンプ","集英社",300,60.3,"2016/9/9 10:00:00"], ["NO12 週刊少年チャンピオン","秋田書店",280,23.5,"2015/5/1 11:30:00"], ["NO5 月刊少年マガジン","講談社",320,45.1,"2016/7/2 13:30:00"], ["NO13 月刊少年チャンピオン","秋田書店",220,12.6,"2015/11/10 7:30:00"], ["NO6 月刊少年ガンガン","スクウェア",240,33.5,"2016/2/2 7:30:00"], ["NO14 月刊少年エース","KADOKAWA", 330,9.8,"2016/7/1 8:30:00"], ["NO7 月刊少年シリウス","講談社",350,20.2,"2016/11/26 15:00:00"], ["NO15 週刊ヤングジャンプ","集英社",300,33.3,"2014/3/16 8:30:00"], ["NO16 ビッグコミックスピリッツ","小学館",240,11.2,"2014/9/29 11:30:00"], ["NO8 週刊ヤングマガジン","講談社",310,26.7,"2016/8/8 10:00:00"]] |
フェッチ開始位置、フェッチ件数、比較オプションを指定しなかった場合は以下の表示になる。
ViewController.swiftの「検索ボタン押下時の呼び出しメソッド」を以下のコードに変更する。
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 32 33 34 35 36 37 38 39 40 41 42 |
//検索ボタン押下時の呼び出しメソッド func searchBarSearchButtonClicked(searchBar: UISearchBar) { //キーボードをしまう。 testSearchBar.endEditing(true) //検索結果配列を空にする。 searchResult.removeAll() //フェッチリクエストのインスタンスを生成する。 let fetchRequest = NSFetchRequest(entityName: "Book") if(testSearchBar.text != "") { //属性nameに検索文字列を含むデータをフェッチ対象にする。 fetchRequest.predicate = NSPredicate(format:"name CONTAINS %@", testSearchBar.text!) } //フェッチ開始のインデックス番号を2に設定する。 fetchRequest.fetchOffset = 2 //フェッチ件数を5件に設定する。 fetchRequest.fetchLimit = 5 //属性nameをFinderの表示順と同じ順番に並び替える。 fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true, selector: "localizedStandardCompare:")] do { //フェッチリクエストを実行する。 searchResult = try managedContext.executeFetchRequest(fetchRequest) as! [Book] } catch { print(error) } //テーブルを再読み込みする。 testTableView.reloadData() } |
以下は実際のプレイ動画。並び替えたあとの3件目から5件がフェッチされた。
開始位置を2に設定したのに3件目からフェッチされた理由は、インデックス番号は0から始まるためである。
バッチサイズを指定する(fetchBatchSizeプロパティ)
絞り込み条件に適合したデータを一度にフェッチする件数を指定する。
通常は、絞り込み条件に適合したデータはすぐにすべてがフェッチされるが、fetchBatchSizeプロパティに値を設定すると、オブジェクトにアクセスする度に設定した件数ぶんのデータがフェッチされる。
fetchBatchSizeプロパティに値を設定してもしなくても動きが変わらないので、本プロパティに関しては検証を行っていない。
大量データをフェッチするときに不要なデータをフェッチしなくても良くなるので、性能の面で力になってくれそうだ。