如何使用 NSFetchRequest 和 fetchLimit = 1 从核心数据中获取 0 或 1 个实体?
How to fetch 0 or 1 entity with NSFetchRequest and fetchLimit = 1 from Core Data?
在多语言应用程序中,我让用户通过 Sign In with 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”)。它被用来select对应NSPersistentContainer
。此代码有效,与我的问题无关。
我的问题是,当容器中还没有实体(用户从未登录)时,do/try/catch
代码失败并显示 Fatal error: Index out of range
:
不应该 do/try/catch
只捕获这个异常,为什么我的应用程序崩溃以及如何修复我的代码,以便获取 0 或 1 UserEntity
并将其分配给 myUser
?
Swift 中的 do/try/catch
机制捕获 Error
s,它们在其他地方是 throw
n,详情参见 Error Handling。它不是一般的异常处理机制。
特别地,“索引越界”是一个运行时错误并且无法被捕获。它总是会立即终止程序。
如果无法执行提取请求,viewContext.fetch(request)
将引发错误。否则它 return 是一个数组或 零个或多个 个对象。为了检查(至少)一个对象是否被 returned,您必须检查 return 数组的 count
或 isEmpty
属性。
另一种选择(如评论中所述)是使用 first
属性,其中 return 是 Optional
:第一个元素(如果数组不为空),或 nil
。在你的情况下是
do {
myUser = try container.viewContext.fetch(request).first
} catch let error {
print("fetchMyUser fetch error: \(error)")
}
在多语言应用程序中,我让用户通过 Sign In with 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”)。它被用来select对应NSPersistentContainer
。此代码有效,与我的问题无关。
我的问题是,当容器中还没有实体(用户从未登录)时,do/try/catch
代码失败并显示 Fatal error: Index out of range
:
不应该 do/try/catch
只捕获这个异常,为什么我的应用程序崩溃以及如何修复我的代码,以便获取 0 或 1 UserEntity
并将其分配给 myUser
?
Swift 中的 do/try/catch
机制捕获 Error
s,它们在其他地方是 throw
n,详情参见 Error Handling。它不是一般的异常处理机制。
特别地,“索引越界”是一个运行时错误并且无法被捕获。它总是会立即终止程序。
如果无法执行提取请求,viewContext.fetch(request)
将引发错误。否则它 return 是一个数组或 零个或多个 个对象。为了检查(至少)一个对象是否被 returned,您必须检查 return 数组的 count
或 isEmpty
属性。
另一种选择(如评论中所述)是使用 first
属性,其中 return 是 Optional
:第一个元素(如果数组不为空),或 nil
。在你的情况下是
do {
myUser = try container.viewContext.fetch(request).first
} catch let error {
print("fetchMyUser fetch error: \(error)")
}