我写了一个函数来获取CoreData中的数据库。此函数将关闭并运行performBackgroundTask
以获取数据。然后,将结果传递给闭包运行。
我在AppDelegate
中编写了静态属性,以便我轻松访问viewContext
:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
static var persistentContainer: NSPersistentContainer {
return (UIApplication.shared.delegate as! AppDelegate).persistentContainer
}
static var viewContext: NSManagedObjectContext {
return persistentContainer.viewContext
}
// ...
}
以下是我写的使用context
崩溃的函数(不是方法):
func fetch<T>(fetchRequest: NSFetchRequest<T>, keyForOrder: String? = nil, format: String? = nil, keyword: String? = nil, handler: (([T]?)->Void)? = nil) where T:NSManagedObject, T: NSFetchRequestResult {
AppDelegate.persistentContainer.performBackgroundTask{(context: NSManagedObjectContext) in
if let format = format?.trimmingCharacters(in: .whitespacesAndNewlines),
!format.isEmpty,
let keyword = keyword?.trimmingCharacters(in: .whitespacesAndNewlines),
!keyword.isEmpty {
fetchRequest.predicate = NSPredicate(format: format, keyword)
}
if let keyForOrder = keyForOrder {
fetchRequest.sortDescriptors = [NSSortDescriptor(key: keyForOrder, ascending: true)]
}
guard let cats = try? context.fetch(fetchRequest) else { // crash
return
}
context.performAndWait(){ // crash
if let handler = handler {
handler(cats)
}
}
}
}
但如果我用context
替换AppDelegate.viewContext
,则该函数不会崩溃:
func fetch<T>(fetchRequest: NSFetchRequest<T>, keyForOrder: String? = nil, format: String? = nil, keyword: String? = nil, handler: (([T]?)->Void)? = nil) where T:NSManagedObject, T: NSFetchRequestResult {
AppDelegate.persistentContainer.performBackgroundTask{(context: NSManagedObjectContext) in
if let format = format?.trimmingCharacters(in: .whitespacesAndNewlines),
!format.isEmpty,
let keyword = keyword?.trimmingCharacters(in: .whitespacesAndNewlines),
!keyword.isEmpty {
fetchRequest.predicate = NSPredicate(format: format, keyword)
}
if let keyForOrder = keyForOrder {
fetchRequest.sortDescriptors = [NSSortDescriptor(key: keyForOrder, ascending: true)]
}
guard let cats = try? AppDelegate.viewContext.fetch(fetchRequest) else { // crash
return
}
AppDelegate.viewContext.performAndWait(){ // crash
if let handler = handler {
handler(cats)
}
}
}
}
到底发生了什么?
感谢。
答案 0 :(得分:4)
以下是一些问题:
context.performAndWait
并可能导致死锁或崩溃。总的来说,我认为你创造的功能没什么价值。如果它所做的只是一个fetch,那么你应该简单地创建谓词和排序描述符并在viewContext上获取。如果你坚持保留这个函数,那么删除performBackgroundTask,使用viewContext获取,返回结果(而不是回调),只从主线程中调用它。