我编写了一个在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
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
以下是我编写的使用以下函数崩溃的函数(不是方法)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)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我替换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)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
到底是怎么回事?
谢谢。
这里有一些问题:
context.performAndWait
并且可能导致死锁或崩溃。总的来说,我认为您创建的功能几乎没有价值。如果它所做的只是获取,则您只需创建谓词和排序描述符,然后在viewContext上获取。如果您坚持要保留该函数,则删除performBackgroundTask,使用viewContext进行获取,返回结果(而不是回调),并且只能从主线程调用它。
归档时间: |
|
查看次数: |
1035 次 |
最近记录: |