Objective c CoreData应用程序的退出时间太长
我的应用程序在运行时可能会创建/删除数千个托管对象。我使用了辅助Objective c CoreData应用程序的退出时间太长,objective-c,swift,macos,cocoa,core-data,Objective C,Swift,Macos,Cocoa,Core Data,我的应用程序在运行时可能会创建/删除数千个托管对象。我使用了辅助NSManagedObjectContexts(MOCs)和NSPrivateQueueConcurrencyType和NSOperations,以使应用程序更具响应性,并且大多数部分工作正常。但是当我按下⌘如果未保存对象的数量很大,应用程序会在窗口关闭之前挂起一段时间(沙滩球继续旋转…) 在保存主运行中心之前,如何使窗口立即消失? 我试图在AppDelegate中的applications中插入window.close(),但无效
NSManagedObjectContext
s(MOCs)和NSPrivateQueueConcurrencyType
和NSOperation
s,以使应用程序更具响应性,并且大多数部分工作正常。但是当我按下⌘如果未保存对象的数量很大,应用程序会在窗口关闭之前挂起一段时间(沙滩球继续旋转…)
在保存主运行中心之前,如何使窗口立即消失?
我试图在AppDelegate
中的applications中插入window.close()
,但无效
我的删除代码没有什么特别之处,只是层次结构非常大。差不多
let items = self.items as! Set<Item>
Group.removeItems(items)
for i in items {
self.managedObjectContext?.deleteObject(i)
}
当创建/删除的托管对象数量较大时,这不会使窗口首先关闭
然后,根据@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仍然被阻塞,有时甚至是使用相同的测试数据
可在此处找到所使用的方法:、
首先,我用.PrivateQueueConcurrencyType
lazy var backgroundMOC : NSManagedObjectContext = {
let coordinator = self.persistentStoreCoordinator
let moc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
moc.persistentStoreCoordinator = coordinator
moc.undoManager = nil
return 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")
}
}
}
将应用程序shouldTerminate()
更改为
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 profiler工具进行优化,这将帮助您了解代码占用的时间
要隐藏窗口,您可以使用下面的命令,在后台将执行所有coredata处理,一旦完成所有操作,应用程序将终止
[self.window orderOut:nil];
退出应用程序可能需要一段时间,因为它将首先清空队列中的进程。
是否要立即停止丢弃父级或子级MOC中的所有内容?但这将导致数据丢失
如果您有多窗口应用程序,则只关闭窗口,而不退出应用程序
此外,如果您管理得当,数千条条目的处理和保存时间不应超过5秒。您的代码中可能存在一些漏洞,请尝试使用Instruments、CoreData profiler工具进行优化,这将帮助您了解代码占用的时间
要隐藏窗口,您可以使用下面的命令,在后台将执行所有coredata处理,一旦完成所有操作,应用程序将终止
[self.window orderOut:nil];
不应放弃数据更改。即使我在moc.save()
之前添加了windows.close()
,在保存完成之前,窗口仍然会在那里。如果您能向代码展示您是如何编写和保存的,那就太好了。还可以尝试使用coredataprofiler
。我在AppDelegate
中使用了Xcode生成的应用程序shouldTerminate:
进行保存。我认为所花的时间是合理的。我想立即隐藏窗口,让它感觉很快。如果要隐藏窗口,请使用[self.window orderOut:nil]代码>。还更新了答案。谢谢。但我试过了。在保存完成之前,窗口不会隐藏,即使我在moc.save()
之前插入了orderOut()
调用。数据更改不应被丢弃。即使我在moc.save()
之前添加了windows.close()
,在保存完成之前,窗口仍然会在那里。如果您能向代码展示您是如何编写和保存的,那就太好了。还可以尝试使用coredataprofiler
。我在AppDelegate
中使用了Xcode生成的应用程序shouldTerminate:
进行保存。我认为所花的时间是合理的。我想立即隐藏窗口,让它感觉很快。如果要隐藏窗口,请使用[self.window orderOut:nil]代码>。还更新了答案。谢谢。但我试过了。保存完成之前窗口不会隐藏,即使我在moc.save()
.call[[NSRunningApplication currentApplication]hide]之前插入了orderOut()
调用
,从应用程序返回NSTerminator
,应终止:
并让应用程序完成它应该完成的操作。然后调用replyToApplicationShouldTerminate:YES
那么我是否应该在应用程序HouldTerminate:
中启动的NSOperation中执行CoreData MOC保存并调用replyToApplicationShouldTerminate:YES
,然后返回NSTerminater
?否,顺序是:1)。用户命令应用程序退出。2). 应用程序代理收到应用程序应终止:
呼叫。3). 在这种方法中,您必须使用一个)。在后台线程中启动保存进程(b)。返回NSTerminateLater
。4). 保存过程完成后,您应该在主线程上调用replyToApplicationShouldTerminate:YES
。仍然不走运。我在问题中添加了代码。只需在dispatch\u async中包装op.start()
(dispatch\u get\u global\u queue(dispatch\u queue\u PRIORITY\u DEFAULT,0),^{})代码>和self.managedObjectContext.performBlock
中的self.managedObjectContext.save()代码>,从应用程序返回NSTerminateLater
应终止: