Зачем использовать Realm! в Свифт?

Почему Realm использует try! так часто? Похоже, если вы уверены, что ваш звонок не подведет, вы не должны проектировать его на throw - no?

Вот пример, со страницы Swift на realm.io:

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

или

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

Для меня это подразумевает, что они никогда не потерпят неудачу, поэтому зачем нужен конструктор или write() throw?

Ответ 1

Если вы ссылаетесь на примеры в Realm Swift Docs, я подозреваю, что try! используется либерально ради краткости. Пользователю дается быстрый и грязный обзор основных понятий без излишних умственных издержек.

Вероятно, вы будете сталкиваться с ошибками в какой-то момент вашего путешествия, используя Realm. Вы увидите позже в документах, в разделе Realms > Error Handling, где приведен пример do-catch.

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

Для меня это подразумевало, что примеры кода из документов не обязательно являются производственными качествами, и пользователю рекомендуется использовать соответствующие функции обработки ошибок Swift.

Ответ 2

Из руководства Realm Swift 2.1.0 в разделе Writes:

Поскольку транзакции записи могут потенциально терпеть неудачу, как любой другой диск Операции ввода-вывода, как Realm.write(), так и Realm.commitWrite(), отмечены как бросает так, что вы можете справляться и восстанавливаться после сбоев, например, заканчивая дисковое пространство. Других восстановимых ошибок нет. Для краткости наш образцы кода не обрабатывают эти ошибки, но вы, безусловно, должны ваши производственные приложения.

Источник: https://realm.io/docs/swift/latest/#writes

Ответ 3

Способ решения этой проблемы заключается в создании класса 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?
}

Ответ 4

Зачем создавать класс со статическим функционалом, когда мы можем создать расширение Realm?

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
}

Ответ 5

Из документации Realm:

Возможно, вы уже заметили, что мы инициализировали доступ к нашей переменной области, вызывая Realm(). Этот метод возвращает объект Realm, который сопоставляется с файлом с именем "default.realm" в папке "Документы" (iOS) или "Папка поддержки приложений" (OS X) вашего приложения.

При каждом взаимодействии с файловой системой вы рискуете столкнуться с такими ошибками, как проблемы с разрешениями или нехватка дискового пространства. Успех не определен.

Итак, если по какой-либо причине Realm не может создать или записать в файл realm, эти методы, которые вы цитируете, действительно вызывают исключение.

Ответ 6

Я создаю это для простого вызова 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)")
        }
    }
}