gpt4 book ai didi

ios - 即使在核心数据上下文保存后数据也不会持久化

转载 作者:搜寻专家 更新时间:2023-11-01 05:34:15 28 4
gpt4 key购买 nike

我的核心数据的持久性存在一些问题。我正在使用 NSSQLiteStoreType persistentStore(见下文)。在我的应用程序中,每次我修改、创建或删除一些数据时,我都会通过调用 saveContext() 上面的函数立即将这些更改保存在我的核心数据中

但是,有时这些更改不会持久化! (这个不持久化的问题不是每次都会出现,我故意重现这个bug还是没成功)

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

  • 用户修改
  • 保存上下文(patient.managedObjectContext,其中 patient 是链接到所有其他数据实体的主要实体)
  • 使用 AlamoFire 与后端同步
  • 收到后端应答后在data中设置remote id
  • 再次保存上下文(仍然在 Alamofire 完成处理程序中:在主线程中执行,通过打印 Thread.current 检查)

最后,当这个错误发生时,它不仅影响一个数据,而且似乎影响从当前 session (从最后一次打开到关闭)修改和保存的所有数据

这是我的核心数据 Controller 的代码:

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 Controller 。

最佳答案

很难确定,但有一种细节组合会带来麻烦并且可能是导致此问题的原因。你提到

save once again the context (still in the thread of Alamofire)

查看代码我看到了这个:

managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)

然后是这个:

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

因此,您有一个使用主队列并发的上下文,但您只是通过调用 save() 来保存主线程之外的更改。这不好。 Core Data 不是线程安全的,您正在跨线程。

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

关于ios - 即使在核心数据上下文保存后数据也不会持久化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45233510/

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