Ios 为什么领域使用try!斯威夫特?
为什么领域使用Ios 为什么领域使用try!斯威夫特?,ios,swift,error-handling,realm,Ios,Swift,Error Handling,Realm,为什么领域使用try如此频繁?似乎如果您确定您的呼叫不会失败,那么您不应该将其设计为抛出-否 下面是realm.io上Swift页面的一个示例: // Get the default Realm let realm = try! Realm() 或 对我来说,这意味着它们永远不会失败,那么为什么要让构造函数或write()抛出呢?来自领域文档: 到目前为止,您可能已经注意到,我们已经通过调用realm()初始化了对realm变量的访问。该方法返回一个领域对象,该对象映射到应用程序的文档文件夹(
try代码>如此频繁?似乎如果您确定您的呼叫不会失败,那么您不应该将其设计为抛出
-否
下面是realm.io上Swift页面的一个示例:
// Get the default Realm
let realm = try! Realm()
或
对我来说,这意味着它们永远不会失败,那么为什么要让构造函数或write()抛出呢?来自领域文档:
到目前为止,您可能已经注意到,我们已经通过调用realm()初始化了对realm变量的访问。该方法返回一个领域对象,该对象映射到应用程序的文档文件夹(iOS)或应用程序支持文件夹(OSX)下名为“default.Realm”的文件
无论何时与文件系统交互,都可能遇到错误,例如权限问题或磁盘空间不足。成功是不确定的
因此,如果出于任何原因,Realm无法创建或写入Realm文件,那么您引用的这些方法确实会引发异常。如果您引用的是Realm中的示例,我怀疑请尝试为了简洁起见,代码>被大量使用。给用户提供了一个快速而肮脏的核心概念概述,而没有太多的精神负担
在使用领域的过程中,您可能会在某个时候遇到错误。您将在文档后面的部分中注意到,这里给出了一个do-catch
示例
do {
let realm = try Realm()
} catch let error as NSError {
// handle error
}
对我来说,这意味着文档中的代码示例不一定是生产质量,并且鼓励用户使用Swift的相关错误处理功能。来自写入部分的领域Swift 2.1.0指南:
因为写事务可能会像其他磁盘一样失败
IO操作,Realm.write()和Realm.commitWrite()都标记为
抛出,以便您可以处理和从失败中恢复,例如耗尽
磁盘空间。没有其他可恢复的错误。为简洁起见,我们的
代码示例不会处理这些错误,但您当然应该在
您的生产应用程序
来源:我处理这个问题的方法是创建一个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)
}
}
}
多亏了这个解决方案,每当我想从领域读取或写入数据库时,代码看起来更干净:)
我创建这个函数是为了简单的初始化调用
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)")
}
}
}
当我们可以创建领域的扩展时,为什么要用static 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
}
一开始的警告会对新手有所帮助。比起安全的代码,更喜欢简洁的代码实际上是一种好的做法吗?我想没有。谢谢达娜,看起来很干净。但是我不明白如果Realm()失败会发生什么,在这种情况下,返回self.Realm的是什么??非常感谢。不幸的是,它将进入无限循环,应用程序将冻结。所以这里肯定有改进的空间。@james我一直在测试这个解决方案,guard let realm=realm.safeInit()else{return}//然后你的写事务主体:realm.safeWrite{…}@zb1995我已经使用guard let改变了你的方法:)非常好,我刚刚提出了另一个编辑,使safeWrite
方法对于“领域已在写入事务中”异常(例如,如果领域已满)是异步安全的:
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
}