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
}