• トップ
  • ブログ一覧
  • SwiftUIでRealmを使ってみた
  • SwiftUIでRealmを使ってみた

    村中(エンジニア)村中(エンジニア)
    2023.11.29

    IT技術

    実施すること

    SwiftUIでRealmを用いて、CRUD処理を実装する

    はじめに

    SwiftUI上でRealmをどのように用いるかを確認するために公式ドキュメントを参考にして実装した。

    公式ドキュメント
    https://www.mongodb.com/docs/realm/sdk/swift/swiftui-tutorial/

    今回私が作成したコード
    https://github.com/muranakar/ReamSampleInSwiftUI

    まずはRealmのPackageをインストールします

    Realmをインストール

    1. File > Add Packages.... を選択する
    2. 以下のURLをクリップボードにコピー
      https://github.com/realm/realm-swift.git
    3. ①の部分に上記URLを挿入する。②でPackageを導入する
    4. 左下にRealmとRealmDatabaseを表示されていれば準備完了です。

    Modelの実装

    次はModelの実装を行います
    今回は以下のER図で表すテーブル設計を元に実装を進めます

    ItemGroup、Itemを定義する。

    Realmでは以下のようにModelの定義を書きます

    1final class ItemGroup: Object, ObjectKeyIdentifiable {
    2    @Persisted(primaryKey: true) var _id: ObjectId
    3    @Persisted var items = RealmSwift.List<Item>()
    4}
    5
    6final class Item: Object, ObjectKeyIdentifiable {
    7    @Persisted(primaryKey: true) var _id: ObjectId
    8    @Persisted var name = "\(randomAdjectives.randomElement()!) \(randomNouns.randomElement()!)"
    9    @Persisted var isFavorite = false
    10    @Persisted var itemDescription = ""
    11    @Persisted(originProperty: "items") var group: LinkingObjects<ItemGroup>
    12}
    1. @Persisted(primaryKey: true)と追記することで、プライマリーキーを設定可能である
    2. @Persisted var items = RealmSwift.List()で、一つのItemGroupに属したItemをListとして呼び出すことが可能である
    3. @Persisted(originProperty: "items") var group: LinkingObjectsで、ItemGroupに属していることを設定する。

    CRUD処理の実装

    CRUD処理を行うために、以下のリストの手順で簡単なViewを実装する

    1. Content.View
    2. ItemView.View
    3. ItemRow.View
    4. ItemDetailView

    ContentViewを作成

    まずは、ベースとなるContentViewを実装する

    1import SwiftUI
    2import RealmSwift
    3
    4struct ContentView: View {
    5    @State var searchFilter: String = ""
    6    @ObservedResults(ItemGroup.self) var itemGroups
    7
    8    var body: some View {
    9        if let itemGroup = itemGroups.first {
    10            ItemsView(itemGroup: itemGroup)
    11        } else {
    12            ProgressView().onAppear {
    13                $itemGroups.append(ItemGroup())
    14            }
    15        }
    16    }
    17}
    1. @ObservedResults(ItemGroup.self) var itemGroupsと実装することで、ローカルに保存されているItemGroupを直接View上で呼び出すことができる

    ItemView、ItemRowを作成

    Itemをリスト表示する画面を作成します。(以下に画像あり)

    • Itemをリスト表示して、項目をタップすると詳細画面に遷移します。
    • 右上の編集ボタンをタップすると、並び替え・削除が可能です。

    1struct ItemsView: View {
    2    @ObservedRealmObject var itemGroup: ItemGroup
    3
    4    var leadingBarButton: AnyView?
    5
    6    var body: some View {
    7        NavigationView {
    8            VStack {
    9                List {
    10                    ForEach(itemGroup.items) { item in
    11                        ItemRow(item: item)
    12                    }
    13                    .onDelete(perform: $itemGroup.items.remove)
    14                    .onMove(perform: $itemGroup.items.move)
    15                }
    16                .listStyle(GroupedListStyle())
    17                    .navigationBarItems(
    18                        leading: self.leadingBarButton,
    19                        trailing: EditButton())
    20                HStack {
    21                    Spacer()
    22                    Button(action: {
    23                        $itemGroup.items.append(Item())
    24                    }) { Image(systemName: "plus") }
    25                }.padding()
    26            }
    27        }
    28    }
    29}
    1. @ObservedRealmObjectのプロパティラッパーで宣言することによって、ローカルデータを簡単に書き換え可能である。
    2. .onDelete(perform: $itemGroup.items.remove)で、 Listの削除実装が可能であり、ローカルデータも書き換えることが可能である。
    3. .onMove(perform: $itemGroup.items.move)で、Listの並び替え実装が可能であり、ローカルデータの並び替えも可能である。
    4. $itemGroup.items.append(Item())で、itemGroupに属するItemを新規追加できる。
    1import SwiftUI
    2import RealmSwift
    3
    4struct ItemRow: View {
    5    @ObservedRealmObject var item: Item
    6
    7    var body: some View {
    8        NavigationLink(destination: ItemDetailsView(item: item)) {
    9            Text(item.name)
    10            if item.isFavorite {
    11                Image(systemName: "heart.fill")
    12            }
    13        }
    14    }
    15}

    ItemDetailViewを作成

    Itemの詳細画面の実装です。(以下に画像あり)

    • 右上のハートボタンをタップすると、isFavariteの値の切り替えです。
    • 「wiggly twister」という値が入力されているTextFieldをタップすると、編集が可能です

    1import SwiftUI
    2import RealmSwift
    3
    4struct ItemDetailsView: View {
    5    @ObservedRealmObject var item: Item
    6
    7    var body: some View {
    8        VStack(alignment: .leading) {
    9            Text("Enter a new name:")
    10            TextField("New name", text: $item.name)
    11                .navigationBarTitle(item.name)
    12                .navigationBarItems(trailing: Toggle(isOn: $item.isFavorite) {
    13                    Image(systemName: item.isFavorite ? "heart.fill" : "heart")
    14                })
    15        }.padding()
    16    }
    17}
    1. TextField("New name", text: $item.name)で、itemnameを書き換えることができる。
    2. Toggle(isOn: $item.isFavorite) で、itemisFavoriteを書き換えることができる。

    まとめ

    CRUDの実装程度であれば、簡単に実装することができました。
    SwiftUIのTextFieldやList に、ObservedRealmObjectObservedResultsを用いた値を直接入れることによって、書き換え・更新が実装されることは非常に便利でした。
    ただ、今回はチュートリアルということもあり、Realmに依存したViewになってしまっているので、実際の業務で使用する場合は注意が必要だと感じました。

    村中(エンジニア)

    村中(エンジニア)

    おすすめ記事