我的应用程序(Xcode 9.2,Swift 4)使用UIManagedDocument作为基本核心数据堆栈。一切都运行良好好几个月,但最近我注意到几个案例,应用程序将无法为现有用户加载,因为核心数据init没有完成。这通常发生在应用程序崩溃后(我想但不确定)。
我已经能够在调试器上重新创建问题并将问题缩小到以下情况:
应用启动 - >调用核心数据启动 - > UIManagedDocument对象是init'd - >检查doc status == closed - >在doc上调用open() - > open永远不会完成 - 永远不会调用回调闭包。
我已经将UIManagedDocument子类化了,所以我可以覆盖configurePersistentStoreCoordinator()
来检查它是否到达那个点,但事实并非如此。永远不会调用handleError()
的子类覆盖。
open()
进程永远不会达到这一点。如果我暂停调试器,我可以看到的是,在与打开过程相关的互斥/信号量上阻塞了几个线程:
第二个线程(11)似乎正在处理某种文件冲突,但我无法理解为什么以及为什么。当我在打开文件之前检查documentState
时,我可以看到它的值为[.normal, .closed]
这是初始化文档的代码 - 非常直接,并且可以按预期用于大多数用途和用例:
class MyDataManager {
static var sharedInstance = MyDataManager()
var managedDoc : UIManagedDocument!
var docUrl : URL!
var managedObjContext : NSManagedObjectContext {
return managedDoc.managedObjectContext
}
func configureCoreData(forUser: String, completion: @escaping (Bool)->Void) {
let dir = UserProfile.profile.getDocumentsDirectory()
docUrl = dir.appendingPathComponent(forUser + GlobalDataDocUrl, isDirectory: true)
managedDoc = UIManagedDocument(fileURL: docUrl)
//allow the UIManagedDoc to perform lieghtweight migration of the DB in case of small changes in the model
managedDoc.persistentStoreOptions = [
NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true
]
switch (self.managedDoc.documentState)
{
case UIDocumentState.normal:
DDLogInfo("ManagedDocument is ready \(self.docUrl)")
case UIDocumentState.closed:
DDLogInfo("ManagedDocument is closed - will open it")
if FileManager.default.fileExists(atPath: self.docUrl.path) {
self.managedDoc.open() { [unowned self] (success) in
DDLogInfo("ManagedDocument is open result=\(success)")
completion(success)
}
}
else{
self.managedDoc.save(to: self.managedDoc.fileURL, for: .forCreating) { [unowned self] (success) in
DDLogInfo("ManagedDocument created result=\(success) ")
completion(success)
}
}
case UIDocumentState.editingDisabled:
fallthrough
case UIDocumentState.inConflict:
fallthrough
case UIDocumentState.progressAvailable:
fallthrough
case UIDocumentState.savingError:
fallthrough
default:
DDLogWarn("ManagedDocument status is \(self.managedDoc.documentState.rawValue)")
}
}
}
再次 - managedDoc.open()
的闭包回调永远不会被调用。好像文件处于某种不良状态,无法打开。
顺便说一句,如果我将app容器从设备复制到我的mac并打开SQLLite存储,我可以看到所有内容都按预期存在。