私のRealmの使用方法についてご紹介します。この記事では、Realmの基本的な定義と、個人開発での利用方法に焦点を当て、Repositoryパターンの実装について説明します。
今回は、こちらの個人開発で使用したRealmの定義とリポジトリーを切り出して説明します。もしよろしければ実際にアプリをダウンロードして使用してみてください。そして、星5をください🙇♂!!
では説明に進みます。
Repositoryパターンを用いる目的
Repositoryパターンを採用する主な目的は、データ管理するツールであるRealmが将来的にサービス終了する可能性がある場合、データを簡単に他のツール(例:CoreDataやSwiftData)に移行しやすくできます。もしRealmで定義したモデルクラスをViewControllerなどで直接使用している場合、ツールの変更に伴い、多くのコードを書き直す必要があります。しかし、Repositoryパターンを利用してRealmモデルを構造体に変換するRepositoryクラスを作成すれば、移行時に修正が必要なコードを最小限に抑えることができます。
モデル定義
以下に、実際のコードの例を挙げ、その説明を加えます。
CharacterRecognition 構造体
struct CharacterRecognition {
var uuidString = UUID().uuidString
var title: String
var content: String
var createdAt: Date = Date()
var uuid: UUID? {
UUID(uuidString: uuidString)
}
}
RealmCharacterRecognition クラス
class RealmCharacterRecognition: Object {
@Persisted(primaryKey: true)
var uuidString = ""
@Persisted
var title: String
@Persisted
var content: String
@Persisted
var createdAt: Date
var uuid: UUID? {
UUID(uuidString: uuidString)
}
convenience init(title: String, text: String, createdAt: Date) {
self.init()
self.title = title
self.content = text
self.createdAt = createdAt
}
}
CharacterRecognition
とRealmCharacterRecognition
は、それぞれデータのモデル定義を行っています。RealmCharacterRecognition
はRealmでのデータ管理で用いており、ViewControllerなどで直接使用することは避けます。データを保存する際はRealmCharacterRecognition
に変換して保存し、ViewControllerで使用する際はCharacterRecognition
に変換して利用するように実装しました。
RealmCharacterRecognition ⇔ CharacterRecognition の変換
private extension CharacterRecognition {
// RealmCharacterRecognitionからCharacterRecognitionへの変換
init(managedObject: RealmCharacterRecognition) {
self.uuidString = managedObject.uuidString
self.title = managedObject.title
self.content = managedObject.content
self.createdAt = managedObject.createdAt
}
// CharacterRecognitionからRealmCharacterRecognitionへの変換
func managedObject() -> RealmCharacterRecognition {
let realmCharacterRecognition = RealmCharacterRecognition()
realmCharacterRecognition.uuidString = self.uuidString
realmCharacterRecognition.title = self.title
realmCharacterRecognition.content = self.content
realmCharacterRecognition.createdAt = self.createdAt
return realmCharacterRecognition
}
}
CharacterRecognition
構造体とRealmCharacterRecognition
クラスの相互変換を行うための拡張です。以下の実装を行うことによって、RealmCharacterRecognition
⇔ CharacterRecognition
の相互変換が楽に実装できます。
Repositoryクラスの作成
CharacterRecognitionRepository クラス
final class CharacterRecognitionRepository {
private let realm = try! Realm()
// 文字認識データの読み込み
func loadCharacterRecognition(ascending: Bool) -> [CharacterRecognition] {
// Realmから文字認識データを取得
let realmCharacterRecognitions = realm
.objects(RealmCharacterRecognition.self)
.sorted(byKeyPath: "createdAt", ascending: ascending)
// Realmオブジェクトを構造体に変換して配列に格納
let realmCharacterRecognitionsArray = Array(realmCharacterRecognitions)
let characterRecognitions = realmCharacterRecognitionsArray.map { CharacterRecognition(managedObject: $0) }
return characterRecognitions
}
// 文字認識データの検索
func loadCharacterRecognition(ascending: Bool, text: String) -> [CharacterRecognition] {
// Realmから文字認識データを取得し、テキストでフィルタリング
let realmCharacterRecognitions = realm
.objects(RealmCharacterRecognition.self)
.sorted(byKeyPath: "createdAt", ascending: ascending)
.filter("content CONTAINS '\(text)' OR title CONTAINS '\(text)'")
// Realmオブジェクトを構造体に変換して配列に格納
let realmCharacterRecognitionsArray = Array(realmCharacterRecognitions)
let characterRecognitions = realmCharacterRecognitionsArray.map { CharacterRecognition(managedObject: $0) }
return characterRecognitions
}
// 文字認識データの追加
func appendCharacterRecognition(characterRecognition: CharacterRecognition) {
try! realm.write {
let realmCharacterRecognition = characterRecognition.managedObject()
realm.add(realmCharacterRecognition)
}
}
// 文字認識データの更新
func updateCharacterRecognition(characterRecognition: CharacterRecognition) {
try! realm.write {
let realmCharacterRecognition = realm.object(ofType: RealmCharacterRecognition.self, forPrimaryKey: characterRecognition.uuidString)
realmCharacterRecognition?.title = characterRecognition.title
realmCharacterRecognition?.content = characterRecognition.content
}
}
// 文字認識データの削除
func removeCharacterRecognition(characterRecognition: CharacterRecognition) {
guard let countHistory = realm.object(
ofType: RealmCharacterRecognition.self,
forPrimaryKey: characterRecognition.uuidString
) else { return }
// データを削除
try! realm.write {
realm.delete(countHistory)
}
}
}
このRepositoryクラスは、文字認識データの管理を行い、データの読み込み、検索、追加、更新、削除を行います。さらに、構造体とRealmモデルの相互変換もこのクラスで行います。
まとめ
この記事では、Realmの基本的な使い方と、Repositoryパターンを利用したデータ管理のアプローチについて説明しました。この方法を取り入れることで、将来的なデータストレージツールの変更にも柔軟に対応できるようになります。ぜひ参考にしてみてください。
余談
こちらの方法は、アプリ道場サロンというオンラインサロンのコードレビュー会という勉強会で教えていただきました。
iOSでのアプリ開発に興味のある方がぜひ!おすすめです!