为什么Realm会尝试使用!在斯威夫特?

Jas*_*ach 25 error-handling realm ios swift

为什么Realm try!经常使用?看起来如果你确定你的电话不会失败那么你就不应该把它设计成throw- 不是吗?

这是一个例子,来自realm.io上的Swift页面:

// Get the default Realm
let realm = try! Realm()
Run Code Online (Sandbox Code Playgroud)

要么

// Persist your data easily
try! realm.write {
  realm.add(myDog)
}
Run Code Online (Sandbox Code Playgroud)

对我来说,这意味着它们永远不会失败,为什么构造函数或write()抛出?

小智 25

如果你指的是Realm Swift Docs中的例子,我怀疑try!是为了简洁而自由使用.用户可以快速而肮脏地概述核心概念,而无需过多的精神开销.

您可能在使用Realm的旅途中遇到错误.您将在稍后的文档中注意到,在Realms> Error Handling部分中do-catch给出了一个示例.

do {
  let realm = try Realm()
} catch let error as NSError {
  // handle error
}
Run Code Online (Sandbox Code Playgroud)

对我而言,暗示来自文档的代码示例不一定是生产质量,并且鼓励用户使用Swift的相关错误处理功能.

  • 开始时发出警告会帮助新手。 (3认同)
  • 更喜欢简洁而不是安全代码实际上是一个好习惯吗?我想不是。 (2认同)

JDu*_*une 15

从Writes部分的Realm Swift 2.1.0指南:

由于写入事务可能会像任何其他磁盘IO操作一样失败,因此Realm.write()和Realm.commitWrite()都被标记为throws,因此您可以处理并从磁盘空间不足等故障中恢复.没有其他可恢复的错误.为简洁起见,我们的代码示例不处理这些错误,但您肯定应该在生产应用程序中.

来源:https://realm.io/docs/swift/latest/#writes


da-*_*-na 7

我处理这个问题的方法是创建一个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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

感谢这个解决方案,每当我想从领域读取或写入db时,代码看起来都更清晰:)

DatabaseManager.write(realm: realm) {
    let queryResult = self.realm.objects(Cookies.self).filter("cookieId == %@", cookieId)
    let cookie = queryResult.first
    cookie?.expirationDate = expirationDate as NSDate?
}
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,它将进入无限循环,应用程序将冻结.所以这里肯定有改进的空间. (10认同)
  • 谢谢da-na,看起来很干净.但是我不明白如果Realm()失败会发生什么,在那种情况下返回self.realm会是什么?谢谢!! (3认同)

Pab*_*mez 5

当我们可以创建 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用示例

旧的不安全代码:

let realm = try! Realm()
try! realm.write {
    // Your write transaction body
}
Run Code Online (Sandbox Code Playgroud)

使用此扩展进行安全重构:

guard let realm = Realm.safeInit() else {
    // Track Error
    return 
}
realm.safeWrite {
   // Your write transaction body as before
}
Run Code Online (Sandbox Code Playgroud)