【问题标题】:How to fetch 0 or 1 entity with NSFetchRequest and fetchLimit = 1 from Core Data?如何使用 NSFetchRequest 和 fetchLimit = 1 从核心数据中获取 0 或 1 个实体?
【发布时间】:2021-10-09 21:32:24
【问题描述】:

在一个多语言应用程序中,我让用户通过 Apple、Google 或 Facebook 登录,然后将他们的数据(用户 ID、给定、姓氏等)存储到 UserEntity

创建实体时,我将stamp 属性设置为当前纪元秒数。

然后在我的自定义视图模型中,我尝试使用以下代码获取至少一个用户并将其分配给@Published var,以便我的应用知道该用户是否已经登录:

class UserViewModel: ObservableObject {
    @Published var myUser: UserEntity?

    init(language: String) {
        fetchMyUser(language: language)
    }
    
    func fetchMyUser(language:String) {
        print("fetchMyUser language=\(language)")
        guard let container = PersistenceController.shared[language]?.container else { return }
        let request = NSFetchRequest<UserEntity>(entityName: "UserEntity")
        request.sortDescriptors = [ NSSortDescriptor(keyPath: \UserEntity.stamp, ascending: false) ]
        request.fetchLimit = 1
        
        do {
            myUser = try container.viewContext.fetch(request)[0]
        } catch let error {
            print("fetchMyUser fetch error: \(error)")
        }
    }
}

注意:请忽略language 字符串参数(“en”、“de”或“ru”)。它用于选择相应的NSPersistentContainer。此代码有效,与我的问题无关。

我的问题是do/try/catch 代码在容器中还没有实体(用户从未登录)时以Fatal error: Index out of range 失败:

do/try/catch 不应该只捕获这个异常,为什么我的应用程序崩溃以及如何修复我的代码,以便获取 0 或 1 UserEntity 并分配给 myUser

【问题讨论】:

  • do/try/catch not 捕获 index-out-of-bounds 错误。您必须检查返回对象的数量(或使用count(for: fetchRequest))。
  • 为避免在访问第一个元素时出现此类错误,请使用 (request).first 而不是使用 (request)[0]

标签: ios swift core-data try-catch outofrangeexception


【解决方案1】:

Swift 中的do/try/catch 机制在其他地方捕获Errors,它们是thrown,有关详细信息,请参阅Error Handling。它不是通用的异常处理机制。

特别是,“索引超出范围”是一个运行时错误并且不能被捕获。它总是会立即终止程序。

viewContext.fetch(request) 如果无法执行获取请求,则会引发错误。否则,它返回一个数组或零个或多个 个对象。为了检查是否(至少)返回了一个对象,您必须检查返回数组的countisEmpty 属性。

另一个选项(如 cmets 中所述)是使用 first 属性,该属性返回 Optional:第一个元素(如果数组不为空)或 nil。在你的情况下,那将是

do {
    myUser = try container.viewContext.fetch(request).first
} catch let error {
    print("fetchMyUser fetch error: \(error)")
}

【讨论】:

  • 谢谢,马丁,现在可以了。在我的 SiwftUI 视图中,我如何检查 @Published var 以了解用户已登录的事实?我试过if userViewModel.$myUser != nil 但编译器说它永远不会为空
  • @AlexanderFarber:恐怕我无法帮你解决这个问题 :( 你可以发布一个新问题,我相信一些 SwiftUI 专家知道答案。
猜你喜欢
  • 2011-02-19
  • 2013-02-13
  • 1970-01-01
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
  • 2012-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多