0%

CoreData整理

看过几次 core data by tutorials 了,感觉每次用到还想重新看过,又是不整理的锅。
core data by tutorials 7th now reading.

  1. 使用自带的core data
  2. NSManagedObject Subclass
  3. Core data stack
  4. 问题
    1. must specify an inverse relationship
    2. background managed object context
    3. NSPersistentContainer 及 NSFetchedResultsControllerDelegate
    4. core data xcode debug
  5. 参考

使用自带的core data

Data Model editor
entity
attribute
relationship

func save(name:String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }

let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Person", in: managedContext)!
let person = NSManagedObject(entity: entity, insertInto: managedContext)

person.setValue(name, forKeyPath: "name")

do {
try managedContext.save()
people.append(person) } catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)") }
}

func fetch() {
//1
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
//2
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Person")
//3
do {
people = try managedContext.fetch(fetchRequest)
}
catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)") }
}

NSManagedObject Subclass

就是model你的数据。
选中 .xcdatamodeld 然后生成 create nsmanagedObject Subclass

Core data stack

iOS10 新加 NSPersistentContainer,可以管理下面四个属性

  • NSManagedObjectModel,类似表结构,ruantime时候,把 xcdatamodel 编辑的文件初始化成 NSManagedObjectModel
  • NSPersistentStore,读取写入存储,sqlite、json、xml、inmemory
  • NSPersistentStoreCoordinator,介于 NSManagedObjectModel 和 NSPersistentStore 之间,多一层抽离可消除彼此细节依赖,使 NSManagedObjectModel 不用知道用了什么介质存储数据,只管存就行;而且如果你有多个持久化存储,那么持久化存储协调器向托管上下文提供了一个统一的接口。
  • NSManagedObjectContext
    • 管理所创建对象的生命周期
    • 管理对象必须有相应的context
    • 非线程安全,只能在统一线程中创建context和管理对象

2021-02-20 72

class CoreDataStack {
private let modelName: String
init(modelName: String) { self.modelName = modelName }

private lazy var storeContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: self.modelName) container.loadPersistentStores { (storeDescription, error) in if let error = error as NSError? { print("Unresolved error \(error), \(error.userInfo)") } } return container }()
}

lazy var managedContext: NSManagedObjectContext = { return self.storeContainer.viewContext }()

func saveContext () {
guard managedContext.hasChanges else { return }
do { try managedContext.save() }
catch let error as NSError
{print("Unresolved error \(error), \(error.userInfo)") }
}

问题

must specify an inverse relationship

Does every Core Data Relationship have to have an Inverse?
想象一个场景:

  1. entity 有个 relationship(non optional,并且不能删除 delete rule=deny) r (没有inverse relationship)
  2. entity set r = oneR
  3. relationship 删除 oneR
  4. coredata save
  5. 一般情况下我们会觉得肯定保存失败,但是结果确实可以。原因就是因为没有inverse,导致relationship变化的时候,并没有reflect到entity上,也就不会触发validation

background managed object context

background managed object context,每次都在 new context 所以全都是异步并发无序
performBackgroundTask,都在一个 context 里,异步但是有序队列

NSPersistentContainer 及 NSFetchedResultsControllerDelegate

persistentStoreCoordinator fetch 的时候不会触发 delegate 方法,调试了半天。

core data xcode debug

xcode scheme 设置中 Run → Arguments → Arguments passed on launch 添加如下配置

-com.apple.CoreData.SQLDebug 1 (1,2,3都可以,显示级别不一样)
-com.apple.CoreData.ConcurrencyDebug 1
-com.apple.CoreData.MigrationDebug 1

cd

参考

core data debuge setting
Core Data. How to swap NSPersistentStores and inform NSFetchedResultsController?
Preload Sqlite data to Core Data
SwiftUI pagination for List object
Core Data Performance: 6 tips you should know
Fetching Remote Data With Core Data Background Context in iOS App
CoreData: CRUD With Concurrency in Swift - Part 2
Closures Capture Semantics: Catch them all!
Using Core Data on Multiple Threads
Functional Swift: Closures { }
Capturing Values In Swift Closures