【SwiftUI】Realm Swiftとは?導入方法とCRUD処理のやり方

この記事からわかること
- Swiftでデータを永続的に
保存 する方法 - Realmとは?
- Realm Swiftライブラリの導入方法
- Swift UIでの使い方
- CRUD処理のやり方
- Realm構造体のwriteメソッドとは?
index
[open]
\ アプリをリリースしました /
環境
- Xcode:16.0
- iOS:18.0
- Swift:5.9
- Realm.Swift:20.0.0
- macOS:Sonoma 14.6.1
iOSアプリに簡単に導入できる「Realmデータベース」についてまとめていきたいと思います。
Realmとは?
Realm(レルム)はiOSやAndroidなどのモバイル向けに開発されたクラスプラットフォームデータベースです。
Realmの特徴はデバイス内にデータベースを作成して使用することです。デバイス自体にデータを保存するためオフライン環境での使用も可能になっており、アプリを停止した場合にもデータが保持されているので再度起動した場合には保存されたデータを使用することが可能になっています。
対応している言語
- Swift
- Objective-C
- Java
- Kotlin
- C#
- JavaScript
またデータベースであることに変わりはないのでテーブル、カラム、レコードといった考え方は同じです。
Realm Swiftライブラリ
SwiftではRealmが「Realm Swift」と呼ばれるライブラリとして提供されています。Swiftではアプリ内からデータを永続的に保存する手段が他にも方法がいくつか存在します。
データを永続的に保存する方法
- テキストファイル
- UserDefaults
- Realm Swift
- KeyChain
それぞれにメリットデメリットがありますが、この中で「Realm Swift」を使う大きなメリットはオリジナルのクラスをそのまま保存できることです。
UserDefaultsではそもそも保存できるデータ型が制限(StringやInt)されており、クラスのまま保存はできません。テキストファイルの場合はJSON形式を使用すれば構造体の保存は可能ですが、操作方法はややこしくコードの見通しも悪くなってしまいます。
またRealm Swiftはデータベース同士のリレーション(関係性)も管理できるのでデータ操作をしやすいのもメリットの1つとなっています。
Realm Swiftの操作方法
Realm Swiftを使用することでデータベース操作(CRUD処理)をSQL文を使用することなくSwiftのクラス(オブジェクト)や配列のように操作できるようになります。
CRUD(クラッド)処理とはデータをデータベースに追加したり、更新したり、削除したりすることを指します。(「Create」、「Read」、「Update」、「Delete」の頭文字)
iOSデバイス内では拡張子が「.realm」とつくファイル名でデータベースが管理されます。このデータベースファイルはアプリがアンインストールされると一緒に削除されます。
Realmの特徴〜まとめ〜
- モバイル向けのデータベース
- Swiftでは「Realm Swift」ライブラリ
- データを永続的に保存可能
- オリジナルのクラスを保存可能
- データベース同士のリレーション(関係性)も管理
- CRUD処理をSwiftのコードで実装
Realm Swiftの導入方法
Realm Swiftはライブラリなので使用するためにはプロジェクトへインポートする必要があります。
ライブラリの追加にはライブラリ管理ツールである「CocoaPods(ココアポッズ)」を使用するのがおすすめです。CocoaPodsがMacに未導入の場合はインストール方法などを下記記事にまとめていますので参考にしてください。
STEP:Realmの導入
- プロジェクトにCocoaPodsを組み込む
- 「PodFile」に「pod 'RealmSwift'」を追記
- ターミナルでpod installを実行
- ファイル内に「import RealmSwift」を追記
- 導入完了!
1.プロジェクトにCocoaPodsを組み込む
ターミナルを起動し以下のコマンドを実行します。
これでSwiftのプロジェクトファイルにCocoaPodsを組み込むことができました。
2.「PodFile」に「pod 'RealmSwift'」を追記
続いてプロジェクトファイル内に追加された「PodFile」を開き「pod 'RealmSwift'
」を追記しておきます。
3.ターミナルでpod installを実行
再びターミナルに戻りpod install
を実行します。以下のように表示されれば成功です。
4.ファイル内に「import RealmSwift」を追記
CocoaPodsを組み込んでいる場合はXcodeの起動は「プロジェクト名.xcworkspace」から起動します。
あとは使用するファイル内でimport RealmSwift
を追記すればRealmが使用可能になります。
Swift UIで扱うRealm操作の基本知識
Swift UI内でRealmを使用するにはまず使用するファイルでライブラリをインポートします。これでRealmを使ったデータベース管理が可能になります。
RealmではデータベーステーブルをObject
を継承したクラスとして定義します。カラムに該当するのがクラスのプロパティとレコード(データそのもの)に該当するのがクラスインスタンス(オブジェクト)になります。
テーブル(オブジェクト)定義の例
name | menu | |
---|---|---|
レコード | Chez Ame | Menuインスタンス1 |
レコード | Kasa Shop | Menuインスタンス2 |
サポートされているデータ型はBool
、Int
、Int8
、Int16
、 Int32
、Int64
、Double
、Float
、String
、Date
、Data
となっており、そのほかにもObject
を継承した独自のクラスもプロパティに保持することが可能です。
レコードのデータ型
テーブルに格納されたレコードは以下のような配列のようなコレクション形式でオブジェクトが格納されている状態(Results<Element>)として取得できます。なので配列とオブジェクトを操作する感覚でデータに参照することができるようになっています。
結果のデータ型
例
Realm構造体
データベースへのCRUD処理はRealm
構造体に定義されている様々なメソッドを使って操作していきます。
なのでまずはRealm
構造体のインスタンス化は必須となってきます。例外が発生する可能性があるのでtry!
の付与が必要になります。
writeメソッド
Realmを使用していく中で重要になってくるのがwrite
メソッドです。データベースへの追加や取得、更新、削除などの処理はwriteトランザクションの中で実行する必要があります。
このメソッドもthrows
がついているので実行時にはtry
を付与する必要があります。
writeトランザクションの中でオブジェクトを操作することでそのオブジェクトがRealmの管理状態になります。
オブジェクトが管理状態になる
例えば追加処理行うadd
メソッドの定義を見てみます。
addメソッドの定義元の解説引用
”追加するオブジェクトは、管理されていないオブジェクトか、このオブジェクトによって既に管理されている有効なオブジェクトである必要があります”
add
やデータを取得するobjects
メソッドを使用すると対象のオブジェクトはRealmの管理状態になります。管理状態になるとオブジェクトとテーブルのデータがリンクした状態になりオブジェクトの値の変更がテーブル内にも反映されます。
クラスをコピーするときはデータの受け渡しが値型ではなく、参照型なのでRealm内にクラスのコピーを作成することでリンク状態になるって感じですかね?
値型:その時時点のデータをそのままコピーするだけ
参照型:データが格納されているメモリの参照を渡すので変更が影響し合う
また管理状態になっているオブジェクトはスレッドセーフではなくなります。そのため異なるスレッドで参照しようとするとアプリがクラッシュするので注意してください。
テーブル定義とCRUD処理方法
ポイント
- データベースに保存するデータクラスの定義
- Create:データの保存
- Read:データの取得
- Update:データの更新
- Delete:データの削除
データベーステーブルクラス定義
Realmのデータベースに保存するテーブル情報をクラスとして定義します。定義するクラスはクラスインスタンスをレコードとして操作するためにObject
に準拠させる必要があります。これはRealmSwiftObject
のタイプエイリアスとなっています。
またプロパティには@Persisted
というプロパティラッパーを付与します。
今回はShop
クラスとMenu
クラスを定義しておきました。
この際にShop側に独自のクラスであるMenu型のプロパティを定義しています。ここにはnil
を許容できるように?
をつけておきます。
nilを許容させないと保存時にエラーになる
バージョンが古いものは@objc dynamicを付与していた
Realmのバージョンが古いプロジェクトなどをみると@Persisted
ではなく、@objc dynamic
を付与していました。この記法はもう古いようなので@Persisted
を使えば問題ないと思います。
おすすめ記事:【Swift UIKit】#selectorとは?使い方と@objcとsender、dynamicの意味まとめ
Create:データの保存
データベースにデータを保存するにはRealm
構造体のインスタンスを生成し、write
メソッドを呼び出してその中でadd
メソッドを呼び出します。add
メソッドの引数に保存したいオブジェクト(レコード)を渡します。
これで各テーブルが生成されレコードが追加されます。Shopテーブルのレコードにはname
プロパティにChez Ame
を、menu
プロパティにMenuクラス型の値を保持したShopクラスのインスタンスを格納していますが、データベースの中には以下のようにクラスごとにデータベースが作成され、必要なテーブル同士が関連づけられながら管理されているような形になっています。
Shopデータベース
name | menu | |
---|---|---|
0 | Chez Ame | Menuテーブル[0] |
Menuデータベース
name | price | |
---|---|---|
0 | Chocolate | 400 |
この場合保存(add)しているのはShop
のみですがプロパティにMenu
(別のRealm Object)を保持している場合そのオブジェクトもデータベースに保存されます。なので取得する際にはMenu
のみを取得することも可能になります。
Read:データの取得
続いて大元であるShopデータベースの全データを取得してみます。全データを取得するにはobjects
メソッドの引数に取り出したいデータベースクラス名をクラス名.self
と記述します。
クリックで全データを出力するボタン
出力結果を見てみると0番目に先ほど追加したデータが確認できます。menu
プロパティの値にはMenu
クラスの値がそのまま保存されているのがわかると思います。
結果
続いてMenuデータベースを取得してみます。次は決め打ちで0番目のデータを取得してみます。
結果
条件を指定してデータを取得する
コレクション形式で全データが取得できたのでCollection型の持つfilter
やRealmCollection型の持つwhere
メソッドなどを使って条件を絞ってデータを取得することが可能です。
Update:データの更新
テーブル内のデータを更新するには対象のレコードを取得して更新します。先にデータを更新するコードを見てみます。
このように取得したレコード情報に対して値を上書きするだけでレコードの値も更新されます。直感的にみるとデータのみを編集しているだけのように見えますが、再度アプリを起動してテーブルの中を参照しても更新された値になっているのを確認してみてください。これはオブジェクトが管理状態になっているためです。
オブジェクトごと更新する
プロパティに値を格納することで対象データを更新していましたが、オブジェクトごと更新することも可能です。オブジェクトごと更新するためには更新対象のオブジェクトと同じIDのオブジェクトを用意してadd(update: .modified)
を使用します。
update: .modified
を指定せずにadd
を使用して既にあるIDのオブジェクトを追加しようとした場合はアプリがクラッシュします。
Delete:データの削除
データベースのデータを削除するにはwrite
トランザクションの中でdelete
メソッドを使用します。引数には削除したいデータ情報を指定します。例えばShopテーブルを削除したい場合は以下のようになります。
条件を指定してデータを削除する
条件にマッチしたデータ(レコード)のみを削除する場合はwhere
メソッドなどで対象のレコードを取得しdelete
メソッドの引数に渡せばOKです。
テーブルを全て削除する
保存しているテーブルを全て削除したい場合はdeleteAll
メソッドを使用します。
おすすめ記事
【SwiftUI】Realmの@ObservedResultsの使い方!値の観測と解凍
【SwiftUI】Realmでプライマリーキーの設定方法!UUIDを指定
【SwiftUI】Realmのマイグレーション方法!Migration is required due to the following errorsの解決法
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。
私がSwift UI学習に使用した参考書
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。