Swift iOS : Core Data

## javascript

Core Data是官方對Sqlite訪問的封裝框架。使用它的好處是:java

  1. 不須要本身引入Sqlite動態庫和建立橋接文件
  2. 不須要使用SQL語言便可訪問Sqlite

使用它的首要需求是引入它,像是這樣:數據庫

import CoreData複製代碼

依然假設咱們的問題是存儲todo項目,字段爲id、item,但願建立數據庫、建立表、插入數據、查詢數據一鼓作氣,代碼以下:app

import UIKit
    import CoreData

    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        var window: UIWindow?
        var context :NSManagedObjectContext!
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
            let dbname = "foo.bar"
            // section : model
            let model = NSManagedObjectModel()
            let entity = NSEntityDescription()
            entity.name = "todo"
            var properties = Array<NSAttributeDescription>()
            let idAttr = NSAttributeDescription()
            idAttr.name = "id"
            idAttr.attributeType = .integer64AttributeType
            idAttr.isOptional = false
            idAttr.isIndexed = true
            properties.append(idAttr)
            let itemAttr = NSAttributeDescription()
            itemAttr.name = "item"
            itemAttr.attributeType = .stringAttributeType
            itemAttr.isOptional = false
            itemAttr.isIndexed = true
            properties.append(itemAttr)
            entity.properties = properties
            model.entities = [entity]

            // section : coordinator
            let coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
            let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
            let docURL = urls[urls.count-1]
            let url = docURL.appendingPathComponent(dbname)

            do {
                try FileManager.default.removeItem(at: url)
            } catch _ {
            }
            do {
                try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
            } catch {
                print("caught: \(error)")
                abort()
            }
            //section : context
            context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
            context.persistentStoreCoordinator = coordinator
            // section : app code

            let todos = [
                (item: "Item 1",id:1),
                (item: "Item 2" ,id:2),
                (item: "Item 3",id:3)
            ]
            for todo in todos {
                let a =  NSEntityDescription.insertNewObject(forEntityName: "todo", into: context)
                a.setValue(todo.item, forKey:"item")
                a.setValue(todo.id, forKey:"id")
            }
            do {
                try context.save()
            } catch _ {
            }
            let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName:"todo")
            //        fetchRequest.predicate = NSPredicate(format: "notificationId = 13")

            do {
                let list = try context.fetch(fetchRequest) as? [NSManagedObject]
                print(list!.count)
                for zoo in list! {
                    print(zoo.value(forKey: "item")!,zoo.value(forKey: "id")!)
                }
            } catch let error as NSError {
                // failure
                print("Fetch failed: \(error.localizedDescription)")
            }
            window?.rootViewController  = UIViewController()
            return true
        }
        func applicationWillTerminate(_ application: UIApplication) {
            if context.hasChanges {
                do {
                    try context.save()
                } catch {
                    print("caught: \(error)")
                    abort()
                }
            }
        }
    }複製代碼

完成要求的一系列的動做的過程當中,首先咱們來看建立數據庫的模型,也就是標註爲:框架

// section : model複製代碼

開始的代碼,它使用了以下的類:fetch

  1. NSManagedObjectModel
  2. NSEntityDescription
  3. NSAttributeDescription

既然是對Sqlite的封裝,那麼這些類顯然分別對應於數據庫、表、字段的。因此儘管代碼看起來有些冗長,意圖卻是比較明顯的。它們等同於建立這樣的表:url

表名:todo
    表字段清單:
        名字  類型 可選 索引
        id   int64 否  是
        item string否  是複製代碼

此處的代碼只是建立了一個內存中的模型,真正的建立使用了NSPersistentStoreCoordinator,在標註爲:spa

// section : coordinator複製代碼

開始的代碼中進行。NSPersistentStoreCoordinator用來把模型和真實的存儲關聯起來。NSPersistentStoreCoordinator的物理存儲使用了Sqlite(NSSQLiteStoreType),可是也能夠使用兩位兩種存儲,分別爲code

// public let NSBinaryStoreType: String
// public let NSInMemoryStoreType: Stringorm

代碼中對FileManager的引用的目的就是在文件存儲中關聯一個文件,若是存在就會刪除它。接下來的NSManaged​Object​Context能夠調用它的save()方法,把當前上下文的數據存儲起來,也能夠使用fetch方法,經過NSFetchRequest指定表名和條件來查詢數據。若是須要插入數據,則須要使用NSEntityDescription的insertNewObject()方法。

這只是一個案例,真正的應用有可能正在編輯數據時,App被退出,那麼數據將不能被保存。若是須要在退出前保存的話,須要在:

func applicationWillTerminate(_ application: UIApplication)     複製代碼

檢測變化,並調用NSManaged​Object​Context.save()來保存數據。

做者

劉傳君。建立過產品,創過業。好讀書,求甚解。能夠經過1000copy#gmail.com聯繫到我

出品

Vue.js小書 www.ituring.com.cn/book/1956

相關文章
相關標籤/搜索