2017-07-21 61 views
1

我正在面对与我的核心数据持久性有关的一些问题。 我正在使用NSSQLiteStoreType persistentStore(请参见下文)。 在我的应用程序,每次我修改,创建或致电上述saveContext()即使核心数据上下文保存后数据也不会持久

,但不时这些改变不会被持久化的功能删除一些数据,我立刻节省了我的coredata这些变化! (非持久性这个问题并不总是存在的,我还是didnt成功复制的目的,这个bug)

下面是其中一个数据的生命周期:

  • 修改用户
  • 保存上下文(patient.managedObjectContext其中患者是链接到所有其它数据实体的主实体)
  • 使用AlamoFire
  • 设定在数据中的远程ID接收后端答案
  • 后后端同步
  • 再次保存上下文(仍在Alamofire完成处理程序:在主线程中执行,通过打印Thread.current检查)

最后,当这个错误发生时,它不会影响只有一个数据,但似乎影响修改并保存当前会话(从上次开盘直至收盘)的所有数据

这里是我的coredatacontroller的代码:

class CoreDataController: NSObject { 

static let shared = CoreDataController() 

var managedObjectContext: NSManagedObjectContext 


override init() { 
    // This resource is the same name as your xcdatamodeld contained in your project. 
    guard let modelURL = Bundle.main.url(forResource: "xxx", withExtension:"momd") else { 
     fatalError("Error loading model from bundle") 
    } 
    // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. 



    guard let mom = NSManagedObjectModel(contentsOf: modelURL) else { 
     fatalError("Error initializing mom from: \(modelURL)") 
    } 
    let psc = NSPersistentStoreCoordinator(managedObjectModel: mom) 

    let options = [ NSInferMappingModelAutomaticallyOption : true, 
        NSMigratePersistentStoresAutomaticallyOption : true] 


    managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) 
    managedObjectContext.persistentStoreCoordinator = psc 

     let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) 
     let docURL = urls[urls.endIndex-1] 
     /* The directory the application uses to store the Core Data store file. 
     This code uses a file named "DataModel.sqlite" in the application's documents directory. 
     */ 
     let storeURL = docURL.appendingPathComponent("xxx.sqlite") 
     do { 
      try psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: options) 
     } catch let error { 
      fatalError("Error migrating store: \(error)") 
     } 
} 

}

这里是我的coredatacontroller是实例:

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate { 

var window: UIWindow? = UIWindow(frame: UIScreen.main.bounds) 
let coreDataController : CoreDataController = CoreDataController.shared 

// FIXME: determiner le comportement attendu pour le badge sur l'icone et l'appliquer !! 
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 
    guard let window = window else { 
     fatalError("Pas de window !!!") 
    } ...... 

,这里是用来每次我的功能我想保存数据在我coreData:

extension NSManagedObjectContext { 

func saveContext() { 
    do { 
     try self.save() 
    } catch let error { 
     print("Failure to save context: \(error)") 
    } 
} 

}

希望这个问题会启发你,并通过提前感谢你的想法!

编辑1:

经过进一步调查,我的同步(包括alamofire请求)的所有过程都在主线程(我的每一步检查通过打印Thread.current)来完成。

 
{number = 1, name = main} 
thread of dataFromJson 
{number = 1, name = main} 
thread of conficthandler 
{number = 1, name = main} 
thread of fetchDataToSync 
{number = 1, name = main} 

此外,检查我的后台数据库和我coredata之间的差异后,似乎coredata未能每个​​数据保存到该应用程序的崩溃(自愿与否),然后应用程序,它会的重新启动“重启'我的coredata控制器。

回答

0

很难确定,但有一个细节的组合可能会造成麻烦,可能是是造成此问题的原因。你提到

再次保存上下文(仍在Alamofire的线程)

通过我看到这个代码展望:

managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) 

,后来有这样的:

do { 
    try self.save() 
} catch let error { 
    print("Failure to save context: \(error)") 
} 

所以,你有一个使用主队列并发的上下文,但你是sav通过调用save()来更改主线程。这不好。核心数据不是线程安全的,而且你正在穿越线程。

要解决这个问题,您需要在您的托管上下文中使用performperformAndWait方法,无论何时将其用于主线程。这包括所有访问,所有可能以任何方式触及上下文的内容 - 获取请求,访问托管对象的属性或关系以及保存更改。这就是Core Data想要处理线程的方式。

+0

谢谢你的建议!经过进一步调查,我的所有同步过程(包括alamofire请求)都在主线程中完成(我通过打印Thread.current来检查每一步)。 此外,检查我的后端数据库和我的coredata之间的差异后,看起来coredata无法保存每个数据,直到应用程序崩溃(自愿或不自愿),然后重新启动将重新启动我的coredata控制器的应用程序。 – PaulM

+0

今天我解决了这个问题,你说得对。 一个回调试图访问coredata nd负责这些错误! – PaulM