多线程上的核心数据操作导致插入但没有获取
Core Data operations on multiple thread causing insertion but no fetching
我正在使用 CoreData 来插入数据和获取数据,因为我有很多数据,所以我在多个线程上使用核心数据以保证线程安全。
问题是我可以在 CoreData 中插入数据,但是从 CoreData 中获取数据时,结果为零,当我终止我的应用程序并从数据库中获取数据时会发生这种情况。这与 NSMangedObjectContext
有关,但我无法弄清楚。
这是我的代码片段:
class CoreDataManager {
static let sharedManager = CoreDataManager()
private init() {}
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "My_Contacts")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func saveContext() {
let context = CoreDataManager.sharedManager.persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
func insertContact(id:Int, firstName : String,lastName : String,emaild : String,isFavorite : Bool,phoneNum : String,profilePic : String,sync : Bool) -> Contact? {
let managedContext = CoreDataManager.sharedManager.persistentContainer.viewContext
let privateManagedObjectContext: NSManagedObjectContext = {
//NSPrivateQueueConcurrencyType
let moc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
moc.parent = managedContext
return moc
}()
let entity = NSEntityDescription.entity(forEntityName: "Contact",
in: privateManagedObjectContext)!
let contact = NSManagedObject(entity: entity,
insertInto: privateManagedObjectContext)
contact.setValue(firstName, forKey: "first_name")
contact.setValue(lastName, forKey: "last_name")
contact.setValue(emaild, forKey: "email")
contact.setValue(isFavorite, forKey: "favorite")
contact.setValue(phoneNum, forKey: "phone_number")
contact.setValue(profilePic, forKey: "profile_pic")
contact.setValue(sync, forKey: "syncStatus")
contact.setValue(id, forKey: "contactId")
do {
try privateManagedObjectContext.save()
return contact as? Contact
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
return nil
}
}
func fetchAllContacts() -> [Contact]?{
let managedContext = CoreDataManager.sharedManager.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Contact")
do {
let people = try managedContext.fetch(fetchRequest)
return people as? [Contact]
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
return nil
}
}
}
由于您正在使用多个 MOC(托管对象上下文),因此您需要保存两个上下文
您已将 privateManagedObjectContext
的父项设置为 managedContext
,但您并未保存 managedContext
调用privateManagedObjectContext.save()
后,还需要调用managedContext.save()
so I am using core data on multiple threads in order to be thread-safe
你这是什么意思?使用多线程不会产生任何结果 thread-safe。线程安全与您 运行 在多个线程上毫无问题地编写代码的能力有关,它通常要求您采取一些预防措施来防止线程相互干扰。
The problem is that I am able to insert Data in CoreData, but while fetching from CoreData, the results are zero, this is happening when I kill my app and fetch the data from Database. This has something to do with NSMangedObjectContext but I am not able to figure it out.
您需要了解什么是托管对象上下文。将其视为一个临时工作区:您可以执行获取请求以将对象从持久存储带入托管对象上下文,您可以将新对象添加到上下文,并且可以在上下文中操作对象。在将上下文保存回持久存储之前,您在上下文中所做的更改在上下文之外没有任何意义。
您可能看不到要添加的对象的几个原因是:
您正在添加对象并尝试在不同的上下文中读回它们。
添加对象后永远不会保存上下文。
您保存了添加对象的上下文,但永远不会保存父上下文(托管对象上下文是分层的)。
您尝试在添加对象后保存上下文,但保存失败。
您在多个线程中使用相同的上下文,而没有注意序列化上下文中的操作(也就是说,您的代码不是 thread-safe).
要解决这个问题,您真正应该做的是让自己回到可以可靠地存储和检索对象的状态。尝试只使用一个线程并确保您的操作有效。如果他们不这样做,请先修复它。接下来,深入了解托管对象上下文的工作原理和使用方法。最后,继续阅读 concurrency and Core Data。
我正在使用 CoreData 来插入数据和获取数据,因为我有很多数据,所以我在多个线程上使用核心数据以保证线程安全。
问题是我可以在 CoreData 中插入数据,但是从 CoreData 中获取数据时,结果为零,当我终止我的应用程序并从数据库中获取数据时会发生这种情况。这与 NSMangedObjectContext
有关,但我无法弄清楚。
这是我的代码片段:
class CoreDataManager {
static let sharedManager = CoreDataManager()
private init() {}
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "My_Contacts")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func saveContext() {
let context = CoreDataManager.sharedManager.persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
func insertContact(id:Int, firstName : String,lastName : String,emaild : String,isFavorite : Bool,phoneNum : String,profilePic : String,sync : Bool) -> Contact? {
let managedContext = CoreDataManager.sharedManager.persistentContainer.viewContext
let privateManagedObjectContext: NSManagedObjectContext = {
//NSPrivateQueueConcurrencyType
let moc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
moc.parent = managedContext
return moc
}()
let entity = NSEntityDescription.entity(forEntityName: "Contact",
in: privateManagedObjectContext)!
let contact = NSManagedObject(entity: entity,
insertInto: privateManagedObjectContext)
contact.setValue(firstName, forKey: "first_name")
contact.setValue(lastName, forKey: "last_name")
contact.setValue(emaild, forKey: "email")
contact.setValue(isFavorite, forKey: "favorite")
contact.setValue(phoneNum, forKey: "phone_number")
contact.setValue(profilePic, forKey: "profile_pic")
contact.setValue(sync, forKey: "syncStatus")
contact.setValue(id, forKey: "contactId")
do {
try privateManagedObjectContext.save()
return contact as? Contact
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
return nil
}
}
func fetchAllContacts() -> [Contact]?{
let managedContext = CoreDataManager.sharedManager.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Contact")
do {
let people = try managedContext.fetch(fetchRequest)
return people as? [Contact]
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
return nil
}
}
}
由于您正在使用多个 MOC(托管对象上下文),因此您需要保存两个上下文
您已将 privateManagedObjectContext
的父项设置为 managedContext
,但您并未保存 managedContext
调用privateManagedObjectContext.save()
后,还需要调用managedContext.save()
so I am using core data on multiple threads in order to be thread-safe
你这是什么意思?使用多线程不会产生任何结果 thread-safe。线程安全与您 运行 在多个线程上毫无问题地编写代码的能力有关,它通常要求您采取一些预防措施来防止线程相互干扰。
The problem is that I am able to insert Data in CoreData, but while fetching from CoreData, the results are zero, this is happening when I kill my app and fetch the data from Database. This has something to do with NSMangedObjectContext but I am not able to figure it out.
您需要了解什么是托管对象上下文。将其视为一个临时工作区:您可以执行获取请求以将对象从持久存储带入托管对象上下文,您可以将新对象添加到上下文,并且可以在上下文中操作对象。在将上下文保存回持久存储之前,您在上下文中所做的更改在上下文之外没有任何意义。
您可能看不到要添加的对象的几个原因是:
您正在添加对象并尝试在不同的上下文中读回它们。
添加对象后永远不会保存上下文。
您保存了添加对象的上下文,但永远不会保存父上下文(托管对象上下文是分层的)。
您尝试在添加对象后保存上下文,但保存失败。
您在多个线程中使用相同的上下文,而没有注意序列化上下文中的操作(也就是说,您的代码不是 thread-safe).
要解决这个问题,您真正应该做的是让自己回到可以可靠地存储和检索对象的状态。尝试只使用一个线程并确保您的操作有效。如果他们不这样做,请先修复它。接下来,深入了解托管对象上下文的工作原理和使用方法。最后,继续阅读 concurrency and Core Data。