Swift實現CoreData存儲數據

以前寫過一篇介紹iOS數據存儲方法的文章,包含:FMDB,SQLite3 ,Core Data,Plist,偏好設置,歸檔。 連接:www.jianshu.com/p/e88880be7…git

本文則是介紹Swift中CoreData的基本使用。
文中示例代碼GitHub地址:Demogithub

coredata.gif

目錄

1、 圖形化建立模型
2、 手動建立模型並實現AppDelegate中的代碼
3、 建立並實現CoreDataManagersql

1、圖形化建立模型(這一小節的內容個人另外一篇文中也有,如已經熟悉,或想要直接手動建立模型,能夠直接看第二小節正式進入Swift)

建立項目的時候,勾選下圖中的Use Core Data選項,工程中會自動建立一個數據模型文件。固然,你也能夠在開發中本身手動建立。編程

自動建立模型文件

下圖就是自動建立出來的文件swift

建立出來的文件

若是沒有勾選,也能夠在這裏手動建立。數組

手動建立

點擊Add Entity以後,至關一張數據表。表的名稱本身在上方定義,注意首字母要大寫。 在界面中還能夠爲數據實體添加屬性和關聯屬性。app

建立一個數據表

Core Data屬性支持的數據類型以下dom

數據類型

編譯以後,Xcode會自動生成Person的實體代碼文件,而且文件不會顯示在工程中,若是下圖中右側Codegen選擇Manual/None,則Xcode就不會自動生成代碼,咱們能夠本身手動生成。編程語言

6.png

  • 手動生成實體類代碼,選中CoreDataTest.xcdatamodeld文件,而後在Mac菜單欄中選擇Editor,以下圖所示。一路Next就能夠了。
  • 若是沒有選擇Manual/None,依然進行手動建立的話,則會與系統自動建立的文件發生衝突,這點須要注意。
  • 你也能夠不要選擇Manual/None,直接使用系統建立好的NSManagedObject,一樣會有4個文件,只是在工程中是看不到的。

手動建立NSManagedObject

Swift中手動建立出來的是這樣2個文件fetch

還要注意編程語言的選擇,Swift或OC

編程語言

2、手動建立模型並實現AppDelegate中的代碼

講道理,這一節應該是Core Data堆棧的介紹與使用,不過因爲以前的文章中已經有了,這裏就不囉嗦了,咱們直接上圖和代碼。

  1. 以下圖所示,建立模型,我這裏直接建立一個命名爲Model的模型。

    建立模型.png

  2. 建立Person表,兩個屬性name和age,注意右側的Codegen咱們這裏選擇Class Definition,而後直接Command+B編譯代碼,Xcode會自動幫咱們生成Person+CoreDataClass.swiftPerson+CoreDataProperties.swift文件

建立數據表.png

  1. 配置AppDelegate中的代碼,首先導入CoreData頭文件,而後懶加載NSManagedObjectModel

注意modelURL中填寫的是模型文件的名字,而且後綴填寫momd

import CoreData

    lazy var managedObjectModel: NSManagedObjectModel = {
        let modelURL = Bundle.main.url(forResource: "Model", withExtension: "momd")
        let managedObjectModel = NSManagedObjectModel.init(contentsOf: modelURL!)
        return managedObjectModel!
    }()
複製代碼
  1. 懶加載持久化存儲協調器NSPersistentStoreCoordinator
  • sqliteURL是sqlite文件的路徑
  • documentDir是後面加載好了的Document路徑
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        let persistentStoreCoordinator = NSPersistentStoreCoordinator.init(managedObjectModel: managedObjectModel)
        let sqliteURL = documentDir.appendingPathComponent("Model.sqlite")
        let options = [NSMigratePersistentStoresAutomaticallyOption : true, NSInferMappingModelAutomaticallyOption : true]
        var failureReason = "There was an error creating or loading the application's saved data."
        
        do {
            try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: sqliteURL, options: options)
        } catch {
            // Report any error we got.
            var dict = [String: Any]()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as Any?
            dict[NSLocalizedFailureReasonErrorKey] = failureReason as Any?
            dict[NSUnderlyingErrorKey] = error as NSError
            let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 6666, userInfo: dict)
            print("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
            abort()
        }
        return persistentStoreCoordinator
    }()

    lazy var documentDir: URL = {
        let documentDir = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first
        return documentDir!
    }()
複製代碼
  1. 懶加載NSManagedObjectContext
lazy var context: NSManagedObjectContext = {
        let context = NSManagedObjectContext.init(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
        context.persistentStoreCoordinator = persistentStoreCoordinator
        return context
    }()
複製代碼

3、建立並實現CoreDataManager

我通常是把數據存儲方法封裝到一個CoreDataManager中,這樣在之後的使用中比較方便。固然,你也能夠根據本身的需求靈活運用。

  1. 建立一個繼承自NSObjectCoreDataManager.swfit文件,而且import CoreData

    建立CoreDataManager

  2. 實現CoreDataManager的單例,而且拿到AppDelegate中剛纔懶加載的NSManagedObjectContext

swift中建立單例比較方便,直接static let shared = CoreDataManager()

// 單例
    static let shared = CoreDataManager()
    
    // 拿到AppDelegate中建立好了的NSManagedObjectContext
    lazy var context: NSManagedObjectContext = {
        let context = ((UIApplication.shared.delegate) as! AppDelegate).context
        return context
    }()
複製代碼
  1. 實現更新數據的方法

除了查詢數據,其他對數據進行增刪改的時候,都別忘記調用這個方法,只有這個方法執行ok,纔算增刪改完成。

// 更新數據
    private func saveContext() {
        do {
            try context.save()
        } catch {
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
複製代碼
  1. 增長數據(保存數據)
  • 首先運用NSEntityDescription建立出person
  • 而後爲person賦值,最終調用saveContext()方法保存數據
// 增長數據
    func savePersonWith(name: String, age: Int16) {
        let person = NSEntityDescription.insertNewObject(forEntityName: "Person", into: context) as! Person
        person.name = name
        person.age = age
        saveContext()
    }
複製代碼
  1. 獲取全部數據
  • 若是是經過系統自動生成的CoreData文件,Person會自帶一個fetchRequest()的方法,咱們能夠直接經過Person.fetchRequest()的方式拿到personNSFetchRequest對象
  • 而後經過contextfetch(fetchRequest)方法拿到數據數組
// 獲取全部數據
    func getAllPerson() -> [Person] {
        let fetchRequest: NSFetchRequest = Person.fetchRequest()
        do {
            let result = try context.fetch(fetchRequest)
            return result
        } catch {
            fatalError();
        }
    }
複製代碼
  1. 獲取特定條件的數據
  • 能夠利用NSPredicate來過濾出符合必定條件的數據
  • NSFetchRequest中有predicate這樣一個屬性
// 根據姓名獲取數據
    func getPersonWith(name: String) -> [Person] {
        let fetchRequest: NSFetchRequest = Person.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "name == %@", name)
        do {
            let result: [Person] = try context.fetch(fetchRequest)
            return result
        } catch {
            fatalError();
        }
    }
複製代碼
  1. 修改數據
  • 首先獲取到想要修改的數據
  • 而後循環修改就能夠了
  • 最後別忘記save
// 根據姓名修改數據
    func changePersonWith(name: String, newName: String, newAge: Int16) {
        let fetchRequest: NSFetchRequest = Person.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "name == %@", name)
        do {
            // 拿到符合條件的全部數據
            let result = try context.fetch(fetchRequest)
            for person in result {
                // 循環修改
                person.name = newName
                person.age = newAge
            }
        } catch {
            fatalError();
        }
        saveContext()
    }
複製代碼
  1. 根據條件刪除數據
  • 與修改數據同樣,首先拿到符合刪除條件的數據
  • 循環調用contextdelete()方法就能夠了
  • 最後別忘記save
// 根據姓名刪除數據
    func deleteWith(name: String) {
        let fetchRequest: NSFetchRequest = Person.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "name == %@", name)
        do {
            let result = try context.fetch(fetchRequest)
            for person in result {
                context.delete(person)
            }
        } catch {
            fatalError();
        }
        saveContext()
    }
複製代碼
  1. 刪除全部數據
  • 獲取全部數據
  • 循環刪除
  • save
// 刪除全部數據
    func deleteAllPerson() {
        // 這裏直接調用上面獲取全部數據的方法
        let result = getAllPerson()
        // 循環刪除全部數據
        for person in result {
            context.delete(person)
        }
        saveContext()
    }
複製代碼

後記

本文運用一個簡單的示例來講明swift中如何使用CoreData,更多用法或注意事項就不一一列舉了。

本文Demo:github.com/remember17/…
做者GitHub:github.com/remember17

相關文章
相關標籤/搜索