web-dev-qa-db-ja.com

なぜレルムはトライを使うのですか?スウィフトで?

Realmがtry!をそれほど頻繁に使用するのはなぜですか?呼び出しが失敗しないことが確実な場合は、throwに設計しないでください-いいえ?

以下は、realm.ioのSwiftページからの例です。

// Get the default Realm
let realm = try! Realm()

または

// Persist your data easily
try! realm.write {
  realm.add(myDog)
}

私にとってこれは決して失敗しないことを意味するので、なぜコンストラクタまたはwrite()をスローするのですか?

25
Jason Leach

レルムの例を参照している場合 Swift Docs の場合、簡潔にするためにtry!が自由に使用されていると思います。ユーザーには、精神的なオーバーヘッドをあまりかけずに、コアコンセプトの概要がすばやくわかります。

おそらくwillは、Realmを使用する旅の途中でエラーに遭遇します。後でドキュメントの Realms> Error Handling セクションにdo-catchの例が示されていることに気づくでしょう。

do {
  let realm = try Realm()
} catch let error as NSError {
  // handle error
}

私には、ドキュメントのコード例が必ずしも本番品質であるとは限らないことが暗示されています。ユーザーには、Swiftの関連するエラー処理機能を使用することをお勧めします。

25
caseynolan

レルムからSwift 2.1.0の書き込みセクションのガイド:

書き込みトランザクションは他のディスクと同様に失敗する可能性があるため、IO操作、Realm.write()とRealm.commitWrite()の両方がスローとしてマークされているため、不足などの障害を処理および回復できますディスク領域。他に回復可能なエラーはありません。簡潔にするために、サンプルコードではこれらのエラーを処理していませんが、本番環境のアプリケーションでは確実に処理する必要があります

ソース: https://realm.io/docs/Swift/latest/#writes

15
JDune

私がこの問題に対処する方法は、レルムがエラーをスローするというまれなイベントを処理するDatabaseManagerクラスを作成することです。

public class DatabaseManager {

    static var realm: Realm {
        get {
            do {
                let realm = try Realm()
                return realm
            }
            catch {
                NSLog("Could not access database: ", error)
            }
            return self.realm
        }
    }

    public static func write(realm: Realm, writeClosure: () -> ()) {
        do {
            try realm.write {
                writeClosure()
            }
        } catch {
            NSLog("Could not write to database: ", error)
        }
    }
}

その解決策のおかげで、レルムから読み取ったりdbに書き込んだりするときはいつでも、コードがずっときれいに見えます:)

DatabaseManager.write(realm: realm) {
    let queryResult = self.realm.objects(Cookies.self).filter("cookieId == %@", cookieId)
    let cookie = queryResult.first
    cookie?.expirationDate = expirationDate as NSDate?
}
8
da-na

Realmの拡張を作成できるのに、静的funcでクラスを作成するのはなぜですか?

extension Realm {
    static func safeInit() -> Realm? {
        do {
            let realm = try Realm()
            return realm
        }
        catch {
            // LOG ERROR
        }
        return nil
    }

    func safeWrite(_ block: () -> ()) {
        do {
            // Async safety, to prevent "Realm already in a write transaction" Exceptions
            if !isInWriteTransaction {
                try write(block)
            }
        } catch {
            // LOG ERROR
        }
    }
}

使用例

安全でない古いコード:

let realm = try! Realm()
try! realm.write {
    // Your write transaction body
}

この拡張機能を使用した安全なリファクタリング:

guard let realm = Realm.safeInit() else {
    // Track Error
    return 
}
realm.safeWrite {
   // Your write transaction body as before
}
2

レルムのドキュメントから:

これまでに、Realm()を呼び出してレルム変数へのアクセスを初期化していることに気付いたかもしれません。このメソッドは、アプリのDocumentsフォルダー(iOS)またはApplication Supportフォルダー(OS X)の下の「default.realm」というファイルにマップするRealmオブジェクトを返します。

ファイルシステムを操作するときはいつでも、アクセス許可の問題やディスク領域の不足などのエラーが発生するリスクがあります。成功は確かではありません。

そのため、何らかの理由でRealmがレルムファイルを作成または書き込むことができない場合、これらのメソッドは実際に例外をスローします。

1
BergQuester

これは単純なinit呼び出し用に作成します

import RealmSwift

// MARK: - RealmDB

/// RealmDB import realm in foundation, and add is format for refactoring catch
public class RealmDB {

    /// Realm
    public static var realm: Realm? {
        do {
            return try Realm()
        } catch let error {
            NotificationCenter.default.post(name: .logError, object: "Could not access database: \(error)")
            return nil
        }
    }

    /// Write in Realm
    ///
    /// - Parameter writeClosure: Write Closure
    public static func write(writeClosure: @escaping (_ realm: Realm) -> ()) {
        do {
            try self.realm?.write {
                // self.realm has so can `!`
                writeClosure(self.realm!)
            }
        } catch let error {
            NotificationCenter.default.post(name: .logError, object: "Could not write database: \(error)")
        }
    }
}
0
YannSteph