Зачем использовать 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)")
}
}
}