gpt4 book ai didi

objective-c - CoreData 应用程序退出时间过长

转载 作者:行者123 更新时间:2023-11-28 08:50:14 25 4
gpt4 key购买 nike

我的应用程序可能会在运行时创建/删除数以千计的托管对象。我已将辅助 NSManagedObjectContexts(MOCs) 与 NSPrivateQueueConcurrencyTypeNSOperation 一起使用,以使应用程序的响应速度更快,并且大多数部分运行良好。但是当我按下 ⌘Q 并且如果未保存的对象数量很大时,应用程序会在窗口关闭之前挂起一段时间(沙滩球一直在旋转......)。

如何让窗口立即消失, MOC 保存之前?我试图在 AppDelegateapplicationShouldTerminate 中插入 window.close(),但没有效果。

我的删除代码没什么特别的,只是层次结构非常大。有点像

let items = self.items as! Set<Item>
Group.removeItems(items)
for i in items {
self.managedObjectContext?.deleteObject(i)
}

Item 是一个分层实体。 Group 与项具有一对多关系。removeItems 由 CoreData 使用 @NSManaged 生成。

非常感谢。


更新

我尝试了以下代码,保存仍然阻塞了 UI。

@IBAction func quit(sender: AnyObject) {
NSRunningApplication.currentApplication().hide()
NSApp.terminate(sender)
}

func applicationShouldTerminate(sender: NSApplication) -> NSApplicationTerminateReply
{
let op = NSBlockOperation { () -> Void in
do {
try self.managedObjectContext.save()
} catch {
print("error")
}
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
NSApp.replyToApplicationShouldTerminate(true)
})
}

op.start()
return .TerminateLater
}

当创建/删除的托管对象数量很大时,这不会让窗口先关闭。

然后我按照@bteapot 的建议更改为以下内容。还是没有效果。窗口仍然不会立即关闭。

@IBAction func quit(sender: AnyObject) {
NSRunningApplication.currentApplication().hide()
NSApp.terminate(sender)
}

func applicationShouldTerminate(sender: NSApplication) -> NSApplicationTerminateReply {

let op = NSBlockOperation { () -> Void in
self.managedObjectContext.performBlock({ () -> Void in
do {
try self.managedObjectContext.save()
} catch {
print("errr")
}
})

NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
NSApp.replyToApplicationShouldTerminate(true)
})
}

dispatch_async ( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
{() -> Void in
op.start()
})

return .TerminateLater
}

最后我解决了这个问题,虽然 UI 仍然被阻塞有时,即使使用相同的测试数据也是如此。

使用的方法可以在这里找到:https://blog.codecentric.de/en/2014/11/concurrency-coredata/ , Core Data background context best practice , https://www.cocoanetics.com/2012/07/multi-context-coredata/

首先,我用 .PrivateQueueConcurrencyType 创建了一个 backgroundMOC

lazy var backgroundMOC : NSManagedObjectContext = {
let coordinator = self.persistentStoreCoordinator
let moc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
moc.persistentStoreCoordinator = coordinator
moc.undoManager = nil
return moc
}()

然后把它变成原来的 moc。

lazy var managedObjectContext: NSManagedObjectContext = {
var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
// managedObjectContext.persistentStoreCoordinator = coordinator

managedObjectContext.parentContext = self.backgroundMOC
managedObjectContext.undoManager = nil

return managedObjectContext
}()

两种保存方式。

func saveBackgroundMOC() {
self.backgroundMOC.performBlock { () -> Void in
do {
try self.backgroundMOC.save()
NSApp.replyToApplicationShouldTerminate(true)
} catch {
print("save error: bg")
}
}
}

func saveMainMOC() {
self.managedObjectContext.performBlock { () -> Void in
do {
try self.managedObjectContext.save()
self.saveBackgroundMOC()
} catch {
print("save error")
}
}
}

applicationShouldTerminate() 更改为

func applicationShouldTerminate(sender: NSApplication) -> NSApplicationTerminateReply {
if !managedObjectContext.commitEditing() {
NSLog("\(NSStringFromClass(self.dynamicType)) unable to commit editing to terminate")
return .TerminateCancel
}

if !managedObjectContext.hasChanges {
return .TerminateNow
}

saveMainMOC()
return .TerminateLater

它这么慢的原因是我使用的是 NSXMLStoreType 而不是 NSSQLiteStoreType

最佳答案

退出应用程序可能需要一段时间,因为它会首先清空队列中的进程。你想立即放弃丢弃父或子 MOC 中的所有内容吗?但这会导致数据丢失。

如果你有多窗口应用程序,那么只关闭窗口而不退出应用程序。

此外,如果您管理得当,处理和保存数千个条目的时间不应超过 5 秒。您的代码中可能存在一些漏洞,请尝试使用 Instruments 和 CoreData 分析器工具进行优化,这将帮助您了解它消耗的时间量。

要隐藏窗口,您可以使用下面的方法,所有核心数据处理都将在后台进行,一旦一切完成,应用程序将终止。

[self.window orderOut:nil];

关于objective-c - CoreData 应用程序退出时间过长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34434478/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com