Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c CoreData应用程序的退出时间太长_Objective C_Swift_Macos_Cocoa_Core Data - Fatal编程技术网

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
应终止: