【Swift/Realm】Results構造体とは?遅延ロードとキャスト方法
この記事からわかること
- Realm Swiftでデータを取得する方法
- Results<Element>構造体の使い方
- RealmSwift.Listクラスとの違い
- 仕組みと遅延ロードとは?
- Array型やRealmSwift.Listへのキャスト方法
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
Realm Swiftでデータベースからデータを取得した際のデータ型であるResults
構造体についてまとめていきます。
参考文献: Results構造体
RealmのResults構造体とは
@frozen
public struct Results<Element> : Equatable, RealmCollectionImpl where Element : RealmCollectionValue
extension Results: RealmSubscribable
extension Results: Encodable where Element: Encodable
Results
構造体はRealm Swiftに定義されているデータベース内から取得したオブジェクトのクエリ結果を表す型です。クエリとはデータベースからデータを抽出する命令であり、その結果(result)をコレクション形式で保持しています。
let realm = try! Realm()
let travelTable = realm.objects(Travel.self) // Travelが定義してあるとして
print(travelTable)
print("----------")
print(type(of: travelTable))
Results<Travel> <0x140a06570> (
[0] Travel {
id = 6458cf17be73f8895a46429f;
name = 鹿児島旅行;
Date = 2023-05-08 10:29:43 +0000;
},
[1] Travel {
id = 6458cfce532e5dede7667aee;
name = 沖縄旅行;
Date = 2023-05-08 10:32:46 +0000;
}
)
----------
Results<Travel>
コレクション形式で保持しているため、要素番号(インデックス)を指定[1]することで中の要素にアクセスできます。
print(travelTable[1])
print("----------")
print(type(of: travelTable[1]))
Travel {
id = 6458cfce532e5dede7667aee;
name = 沖縄旅行;
Date = 2023-05-08 10:32:46 +0000;
}
----------
Travel
object
やfilter
、where
などデータベースからデータを抽出やフィルタリングする役割を持つメソッドの返り値がResults<Element>
になっています。
let okinawaTravelTable = realm.objects(Travel.self).filter("name = '沖縄旅行'")
またResults
構造体は直接インスタンス化することはできず、クエリ結果としてのみインスタンス化されることが期待されているようです。
let travel = Travel()
travel.name = "東京旅行"
Results<Travel>(travel as! RLMCollection)
// Error:'Results<Element>' initializer is inaccessible due to 'internal' protection level
// 「内部」保護レベルのため、「Results<Element>」のイニシャライザにアクセスできません
Listクラスとの違い
Realm Swiftには別のコレクション形式としてList
クラスが定義されています。こちらはSwiftのArray
と同じような振る舞いをするクラスになっています。Results
構造体は自身で使用することはなく、あくまで結果としてのデータ型であり、List
クラスはテーブル定義や変数の型などにも使用できるデータ型になります。
@State var list:RealmSwift.List<Travel> = RealmSwift.List<Travel>()
Button {
// レコードの生成
let travel = Travel()
travel.name = "沖縄旅行"
list.append(travel)
print(list)
} label: {
Text("Add List")
}
このList
クラスと同じAPIを使用してResults
構造体では要素数の取得やフィルタリングといった機能が利用でき、またメソッドチェーンを使用することで複数の条件を指定することができます。
travelTable.count
travelTable.first!
取得するのはコピーではなく実際のデータ
クエリ結果として取得したResults
インスタンスはデータのコピーではなく、実際のデータと繋がっています。なのでResults
インスタンスへの更新はそのままデータベースの更新になります。
let travelTable = realm.objects(Travel.self).filter("name = '沖縄旅行'")
try! realm.write{
travelTable.first?.name = "Okinawa Travel"
}
遅延ロード:Lazy Loading
データベースには膨大なデータが蓄積されますが、Realm
では読み込みを遅延(遅延ロード:Lazy Loading)させることで高速化を実現
しています。一度に大量のデータを読み込む仕組みに比べて、必要なデータを必要な時にだけ読み込む仕組みにすることでアプリのパフォーマンスを向上させているようです。
これはクエリによるフィルタリングをかけている時にも機能するようで「条件に一致する最初の10個のオブジェクトを取り出す」といったクエリが実行される際には10個以上一致するものがあっても最初の10個の要素のみにアクセスします。
配列へのキャスト
Results
インスタンスはArray
のイニシャライザを使用することで簡単にキャストすることができます。
// Resultsを配列に変換する
let travelTable = realm.objects(Travel.self)
let array:Array<Travel> = Array(travelTable)
print(type(of: array)) // Array<Travel>
RealmSwift.Listへのキャスト
Results
インスタンスはRealmSwift.List
のappend(objectsIn:)
メソッドを使用することでキャストすることができます。Array型
でもRealmSwift.List
に変換可能です。
let travelTable = realm.objects(Travel.self) // Results型
list.append(objectsIn: travelTable) // RealmSwift.List型
or
let travelTable = realm.objects(Travel.self) // Results型
let array:Array<Travel> = Array(travelTable) // Array型
list.append(objectsIn: array) // RealmSwift.List型
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。