CoreData - 簡單 增刪改查

weixin_33850890發表於2018-12-23

1. 建立一個 Data Model 檔案

1.1 建立檔案

new file 中選擇以下檔案建立。顧名思義 Data Model 就是資料庫需要操作的實體,通過檔案的視覺化操作建立一各個實體,這些實體會在 Core Data 資料庫建立的時候生個一個個表(Table)

2625842-b87dbfffd72ef321.png
1.png

1.2 Data Model 具體實現

建立完後我們新增實體、屬性、關係,最後生成的一個 Data Model 檔案如圖

2625842-72012cbd4d373d50.png
2.png

這樣子我們對 Core Data 檔案的操作已經完成了

這裡有一點需要注意的,在舊版中的 XCode 中,沒記錯的話應該是 XCode 7,實體類都是需要自己建立的,但是在新版 XCode 中實體類會自動建立。要想自己建立實體類不使用預設的可以通過以下設定修改

2625842-a1d25e8b52f8e286.png
3.png

2. CoreData 棧建立

我們知道,一個基本的 CoreData 棧由四個部分組成:

  • 託管物件 ( NSManagedObject)
  • 託管物件上下文 ( NSManagedObjectContext)
  • 持久化儲存協調器 (NSPersistentStoreCoordinator)
  • 持久化儲存 ( NSPersistentStore)

一個簡單的 CoreData 棧可以用如下程式碼建立,建立後則可以通過 NSManagedObjectContext 獲取NSManagedObject

import CoreData

class CoreDataStack {
    
    static let sharedInstance = CoreDataStack()
 
    lazy var applicationDocumentsDirectory: NSURL = {
        let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return urls[urls.count-1] as NSURL
    }()
    
    /// 讀取 Data Model (.xcdatamodeld)檔案獲取託管物件模型
    lazy var managedObjectModel: NSManagedObjectModel = {
        // momd 字尾會自動查詢到相應的 Data Model 檔案
        let modelURL = Bundle.main.url(forResource: "Person", withExtension: "momd")!
        return NSManagedObjectModel(contentsOf: modelURL)!
    }()
    
    /// 建立持久化儲存協調器,在用物件模型初始化它以後,給它新增 NSSQLiteStoreType 的持久化儲存。儲存的位置由url指定
    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        var coordinator = NSPersistentStoreCoordinator.init(managedObjectModel: self.managedObjectModel)
        
        // CoreData 資料庫 .sqlite 檔案的路徑
        let url = self.applicationDocumentsDirectory.appendingPathComponent("Person.sqlite")
        print("\(url!)")
        
        var error: NSError? = nil

        do{
            try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
        }catch{
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
        
        return coordinator
    }()
    
    /// 使用 .mainQueueConcurrencyType 選項建立 主上下文,並賦給persistentStoreCoordinator
    lazy var managedObjectContext: NSManagedObjectContext = {
        let coordinator = self.persistentStoreCoordinator
        
        var managedObjectContext = NSManagedObjectContext.init(concurrencyType: .mainQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
    }()
}

需要注意的是,往往一個 CoreData 棧不只有這些東西,比如既然有主上下文,在主執行緒上做資料操作,那麼肯定也有子執行緒上下文,通過 .privateQueueConcurrencyType 建立。以及還有其他的支援等等。我們這裡就用 主上下文 做實驗了

這個時候只要執行獲取上下文,就會在指定目錄下建立好資料庫

let _ = CoreDataStack.shared.mainManagedObjectContext

開啟沙盒 Document 可以看到

2625842-5ff5bdfce5c5a4ca.png
4.png

3. CoreData 增刪改查

對於 增刪改查 操作都可以開啟 上面的 Person.sqlite 檢視結果

3.1 增

// 獲取上下文,獲取的同時初始化了 CoreData 棧
let context = CoreDataStack.shared.mainManagedObjectContext
// 建立要插入的實體
let father = NSEntityDescription.insertNewObject(forEntityName: "Father", into: context) as! Father

// 給實體賦值,其中像 children,grandFather 這種關聯的實體要賦值也需要傳入一個物件
father.name = "Li gang"
father.children = []
//        father.grandFather = ...

// 儲存上下文中所有有更改的資料
context.saveOrRollback()

3.2 查

為什麼不用 增刪改查 的順序而把查放在第二個呢,因為 刪改 前需要先查

let context = CoreDataStack.shared.mainManagedObjectContext
// 通過實體名初始化一個 NSFetchRequest 用於設定查詢條件
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Father")
// 設定查詢條件
request.predicate = NSPredicate(format: "name = %@", "Li gang")
// 設定排序的方式,下面是根據 id 屬性升序排序
request.sortDescriptors = [NSSortDescriptor(key: "id", ascending: true)]
// 獲取結果
let entitys = try! context.fetch(request) as! [Father]

3.3 刪

let context = CoreDataStack.shared.mainManagedObjectContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Father")
request.predicate = NSPredicate(format: "name = %@", "Li gang")
let entitys = try! context.fetch(request) as! [Father]

// 遍歷所有實體,刪除
for entity in entitys {
    context.delete(entity)
}
// 儲存上下文中所有有更改的資料
context.saveOrRollback()

3.4 改

let context = CoreDataStack.shared.mainManagedObjectContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Father")
request.predicate = NSPredicate(format: "name = %@", "Li gang")
let entitys = try! context.fetch(request) as! [Father]

// 遍歷所有實體,修改 name 屬性
for entity in entitys {
    entity.name = "Li lei"
}
// 儲存上下文中所有有更改的資料
context.saveOrRollback()

相關文章