Realm Databaseのバックアップとリストア


Realm Databaseのバックアップとリストア

あまりRealmのバックアップとリストアについての記事が見つからないので投稿します。

環境

環境 バージョン
Xcode 12.0
Swift 5
MacOS Big Sur(11.0.1)

Libraryディレクトリ直下にバックアップ

defaults.realm_bk_yyyy-MM-dd-hh-mm-ssというファイル名で
現在のdefaults.realm(Realm Database本体)をバックアップします。

Hoge.swift

    private func hoge() {
        do {
            let url = try FileManager.default.url(for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            let dateformater = DateFormatter()
            dateformater.dateFormat = "yyyy-MM-dd-hh-mm-ss"
            dateformater.locale = Locale(identifier: "ja_JP")
            let fileName = "default.realm_bk_" + dateformater.string(from: Date())
            try backupLocalStore(storeBackupDirectoryURL: url, backupStoreFilename: fileName)
        } catch {
            print(error.localizedDescription)
        }
    }


    /// Realmを指定の場所にバックアップします。
    /// - Parameters:
    ///   - storeBackupDirectoryURL: バックアップするディレクトリを指定
    ///   - backupStoreFilename: バックアップするファイル名を指定
    /// - Throws: エラー
    private func backupLocalStore(storeBackupDirectoryURL: URL, backupStoreFilename: String) throws {
        let backupURL = storeBackupDirectoryURL.appendingPathComponent(backupStoreFilename)
        do {
            let realm = try Realm()
            realm.beginWrite()
            try realm.writeCopy(toFile: backupURL)
            realm.cancelWrite()
        } catch {
            throw error
        }
    }

Library直下にバックアップが作成されています。

バックアップしたファイルをリストアする

Hoge.swift

    private func hoge() {
        do {
            var url = try FileManager.default.url(for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            url.appendPathComponent("default.realm_bk_2020-11-16-10-46-35")
            try realmRestore(backupFileURL: url)
        } catch {
            print(error.localizedDescription)
        }
    }

    /// Realmをリストアする
    /// - Parameter backupFileURL: バックアップファイル
    /// - Throws: エラー
    private func realmRestore(backupFileURL: URL) throws {
        guard let realmFileUrl = Realm.Configuration.defaultConfiguration.fileURL else {
            throw NSError.init(domain: "Realmのファイルパスが取得できませんでした。", code: -1, userInfo: nil)
        }
        try FileManager.default.removeItem(at: realmFileUrl)
        try FileManager.default.copyItem(at: backupFileURL, to: realmFileUrl)
    }

指定したバックアップファイルでデータベースが復元されているのが確認できるはずです。

懸念事項

今回書いたサンプルコードはRealmが他でアクセスされている事を考慮できていない可能性があります。(特にリストアする時)
ただ、個人アプリ等で絶対にここではアクセスしていないと分かる場面等では利用できるかと思いますので自己責任でご利用ください😇
なにかあればご質問、ご指摘お待ちしております!