Core Data的基本使用簡介

初始化

方法一

建立一個iOS工程,勾選Use Core Data。正則表達式

工程建立完後,XCode將爲咱們生成一個xcdatamodeld文件用於建立實體。咱們能夠在這裏編輯實體,併產生託管對象類。同時,XCode也在AppDelegate.Swift中添加了一些用於支持CoreData的代碼。sql

我在這裏所用的辦法是經過輔助類來設置Core Data,這樣的話,你就能夠將這種辦法運用到本身的項目中了。這也使得Core Data組件變的模塊化,並且易於移植。咱們將經過應用程序委託來惰性地(lazily)建立CoreDataHelper類的實例。下面就來看咱們的方法二數據庫

方法二

這種實例可用來完成下列事項:
一、初始化託管對象模型
二、根據託管對象模型來建立持久化存儲區,並據此初始化持久化存儲協調器
三、根據化持久化存儲協調器來初始化託管對象上下文swift

咱們先建立CoreDataHelper.Swift文件,而且將Subclass類名爲CoreDataHelper。後端

實現CoreDataHelper類

import CoreData
class CoreDataHelper:NSObject {
  // MARK: - Core Data stack
   
    // 這個目錄用來存放應用程序Core Data存儲文件,在當前事例中,會在應用程序的Document目錄下生成名爲「FoodPin.Coredata」文件。
    lazy var applicationDocumentsDirectory: NSURL = {
        let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
        return urls[urls.count-1] as! NSURL
        }()
// 應用程序的託管對象模型。   
    lazy var managedObjectModel: NSManagedObjectModel = {

        let modelURL = NSBundle.mainBundle().URLForResource("FoodPin", withExtension: "momd")!
        return NSManagedObjectModel(contentsOfURL: modelURL)!
        }()
    //持久化協調器
    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
        
        var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("FoodPin.sqlite")
        var error: NSError? = nil
        var failureReason = "There was an error creating or loading the application's saved data."
        if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error: &error) == nil {
            coordinator = nil
            // Report any error we got.
            let dict = NSMutableDictionary()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
            dict[NSLocalizedFailureReasonErrorKey] = failureReason
            dict[NSUnderlyingErrorKey] = error
            error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict as [NSObject : AnyObject])
            
            NSLog("Unresolved error \(error), \(error!.userInfo)")
            abort()
        }
        
        return coordinator
        }()
    //託管對象上下文
    lazy var managedObjectContext: NSManagedObjectContext? = {
        
        let coordinator = self.persistentStoreCoordinator
        if coordinator == nil {
            return nil
        }
        var managedObjectContext = NSManagedObjectContext()
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
        }()
    
    // MARK: - Core Data Saving support
    
    func saveContext () {
        if let moc = self.managedObjectContext {
            var error: NSError? = nil
            if moc.hasChanges && !moc.save(&error) {
               
                NSLog("Unresolved error \(error), \(error!.userInfo)")
                abort()
            }
        }
    }

}

我是絕對絕對不會告訴你上邊的這段代碼是我從AppDelegate.Swift中將有關CoreData的部分剪貼出來生成新的CoreDataHelper類的。數組

建立託管對象模型

command + n以後選擇iOS中的Core Data裏的Data Model文件,點擊Next。
填寫文件名稱,默認名稱是Model。點擊Create以後在工程中就能夠看到一個.xcdatamodeld爲後綴的文件了。安全

實體

託管對象模型由一系列實體描述對象構成,這種對象就叫作實體。實體用來建立託管對象,有了託管對象以後咱們能夠用Swift代碼來操做其中的數據了。app

託管對象模型能夠擁有一個或者多個實體,每一個應用程序的實體數量會有所差異。在製做託管對象以前,首先要把每個實體設計好。實體的設計與傳統的數據庫中數據表的設計是類似的。dom

實體的屬性必須有特定的數據類型,若是想從實體中建立託管對象,那麼咱們一般會根據實體來建立NSManagedObject的子類,但這並非強制性的。採用NSManagedObject的子類確實有好處,好比說能夠在託管對象後面使用「點符號」來訪問相關屬性,這樣可讓代碼便於閱讀。編輯器

按照下面的步驟來添加一個實體:

一、選定Model.xcdatamodeld
二、點擊Add Entity
三、把實體的名稱改成Entity

實體屬性

實體屬性
選擇適合的屬性值在你的屬性名稱後邊。

屬性的各類設置選項

屬性的各類設置選項

Transient

若是在Properties中勾選了這一項,那麼該屬性就不會寫入持久化存儲區了。「不寫入持久化存儲區」聽上去有些奇怪,可是有時,只須要吧特性留在託管對象上下文裏面就好了。比方說,你須要計算某個臨時的值,而這種值就能夠放在transient特性中。

Optional

Optional特性並不必定要有值。全部的特性在剛建出來的時候都是Optional特性。若是某一個不是Optiona特性,那麼在把這非Optional特性放回存儲區的時候,它必須具有有效的值才行。

Indexed

系統會優化Indexed特性以提高搜索效率,但代價是要在底層的持久化存儲區佔用額外的空間。這些額外的空間的大小要根據待索引的數據量來定。若是不打算搜索某個屬性,那麼就不要勾選Indexed,這樣能夠節省一些空間。

Validation

你可使用Validation中的各個選項來阻止不合理的數據進入持久化存儲區。每一種數值型的屬性都支持相同的Validation選項,也就是能夠規定其最小值和最大值。同理,對於字符串類型或者日期類型的屬性來講,能夠限定其字符串長度和日期範圍。

Reg. Ex.

Reg. Ex.Regular Expression(正則表達式)的縮寫,他不只可以限定字符串的最小長度以及最大長度,並且還能實現不少驗證功能。通常來講,咱們會用正則表達式來判斷屬性中的字符串值是否是能與某個特定的模式相匹配。匹配成功了才能將其寫入持久化存儲區。

Default

除了可變數據類型與二進制數據以外,其他類型的屬性均可以具有默認值。

Allows External Storage

開啓了這個選項以後,類型爲二進制數據的屬性就能夠把大量數據保存在持久化存儲區以外了。但若是底層的持久化存儲區是XML格式(iOS不支持這種格式的存儲區),那麼該選項就不起做用了。

建立NSManagedObject的子類

託管對象模型就位以後,咱們就該根據Entity實體來建立NSManagedObject的子類了。

一、選中Entity實體。
二、點擊Editor>Create NSManagedObject Subclass菜單項。
三、確保Model被選中,而後點擊Next。
四、屢次點擊下一步以後,會在項目中生成Entity.swift文件。

在這中間要強調的一點是,要不要勾選 Use scalar properties for primitive data types

勾選上這個選項以後就是使用的是你在定義的時候使用的原始數據類型。
若是沒有勾選的話,就會存在類型的轉化,轉換狀況以下

• String maps to String
• Integer 16/32/64, Float, Double and Boolean map to NSNumber 
• Decimal maps to NSDecimalNumber
• Date maps to NSDate
• Binary data maps to NSData
• Transformable maps to AnyObject

本身試一下,看看勾選以後和沒有勾選生成的Entity.swift文件有什麼區別。

建立託管對象

全部的事情都準備好了以後,如今能夠新建一些託管對象了。

新對象是由NSEntityDescription按照指定的名稱並根據某個特定的實體而建立出來的。除了要指定對象所依據的實體以外,還須要提供託管對象上下文,建立好的託管對象將會放在那個上下文裏面。

let coredataHelper = CoreDataHelper()
        
        if let managedobjectcontext = coredataHelper.managedObjectContext{
            var object = NSEntityDescription.insertNewObjectForEntityForName("Entity", inManagedObjectContext: managedobjectcontext) as! Entity
            object.name = "Hello World Core Data"
            var e:NSError?
            if !managedobjectcontext.save(&e) {
                println("okCould not save \(e), \(e!.userInfo)") }else{
                println("數據存儲成功,哦也")
            }
        }

後端SQL的可見性

按照下列步驟開啓SQL Debug模式

一、點擊Product>Scheme>Edit Scheme ...
二、點擊Run Grocery Dude,並切換到Arguments分頁。
三、點擊Arguments Passed On Launch區域中的「+」按鈕,以新增參數。
四、輸入新參數 -com.apple.CoreData.SQLDebug 3,而後點擊OK。

如今咱們已經開啓了第三級的SQL Debug模式,而後從新運行程序,查看控制檯輸出了什麼。

獲取託管對象

想操做託管對象上下文中的現有數據,就必須先把它獲取(fetch)出來。加入待獲取的數據沒有放在上下文中,那麼Core Data會從底層的持久化存儲區裏面把它拿過來,這個過程對開發者來講是透明的。

要執行獲取操做,就要有NSFetchRequest實例,改實例會返回[AnyObject],這個數組裏面的元素都是託管對象。在執行獲取操做的時候NSFetchRequest會根據特定的實體,把每一個託管對象都放在[AnyObject]這個數組裏面,而且返回給調用者。

var fetchRequest = NSFetchRequest(entityName: "Entity")
            
            var  fetchObjects = managedobjectcontext.executeFetchRequest(fetchRequest, error: &e) as! [Entity]
            for info in fetchObjects{
                println("name: \(info.name)")
                println("+++++++++++++++++++++++")

//修改
info.name = "這塊顯卡有點冷"

if !managedobjectcontext.save(&e){
    println("不能保存\(e!.localizedDescriptoin)")
}

     }

對獲取的請求結果進行排序

NSFetchRequest執行完畢以後會返回一個NSArray,而NSArray自己就支持其中的元素進行排序。咱們能夠給NSFetchRequest配置排序描述符,這樣的話。NSFetchRequest就能夠直接按特定方式獲取到託管對象進行排序了。這個描述符是做爲NSSortDescriptor的實例傳給NSFetchRequest的。

對請求的結果進行篩選

有時咱們並不想把與某個實體有關的所有對象都獲取過來,這時能夠經過謂詞來篩選。咱們採用NSPredicate實例來定義謂詞,並將其傳給NSFetchRequest實例。有了謂詞以後,獲取請求就會根據謂詞中的標準限定獲取到的託管對象的數量。

獲取請求模版

若是咱們每一次獲取託管對象時都要使用手工編寫謂詞格式確實很累人哇。幸虧的是,Xcode的Data Model Designer有預約義獲取請求的功能。這些可複用的模版比謂詞更容易配置,並且還能減小重複代碼。

建立獲取請求模版:

  1. 選中.xcdatamodeld。

  2. 點擊Editot > Add Fetch Rquest。

  3. 而後設置請求模版的名稱。

  4. 點擊+按鈕來配置獲取請求模版。

要想使用獲取請求模版,須要先給託管對象模型發送消息,告訴他將要使用的模版叫作什麼名字。發送完消息以後,就能夠在返回的NSFetchRequest上面操做了。因爲這種獲取請求是根據模版建立出來的,因此咱們無需經過向其發送謂詞來執行篩選操做。

let fetchRequest3 = managedObjectModel.fetchRequestTemplateForName("Name")

Fetching different result types

struct NSFetchRequestResultType : OptionSetType {
    init(rawValue rawValue: UInt)
    static var ManagedObjectResultType: NSFetchRequestResultType { get }
    //返回  ManagedObject  這個是默認的
    static var ManagedObjectIDResultType: NSFetchRequestResultType { get}
    //返回  unique identifiers instead of full- fledged managed objects.
    static var DictionaryResultType: NSFetchRequestResultType { get }
    //返回 字典類型
    static var CountResultType: NSFetchRequestResultType { get }
    // 返回  Returns the count of the objects that match the fetch
request.
}

刪除託管對象

若想刪除託管對象,只須要在包含對象的上下文中調用deleteObject或者deleteObjects。而後用上下文的save方法保存更新數據庫。

託管對象模型的擴展

關係

關係是用來連接實體的。在託管對象模型中使用關係。
咱們把界面的Editor Style 改成 Graph,按下control鍵,用鼠標從一個 實體託向另外一個實體。
當編輯器界面處於Graph風格時,在兩實體之間建立的關係是雙向關係。若是在Table風格的編輯器界面中建立關係,那麼建立出來的可能就是單向關係,此時若是須要創建雙向關係,那麼還必須手動添加反向的那一條關係。

把兩個實體關聯起來以後,咱們就能夠經過關係來訪問相關實體的屬性了。

接下來的問題就是,要想清楚每一個方向上的關係是一對多,仍是一對一。想清楚這個問題以後,你應該就能給關係起一個更爲合適的名字。一對多的關係,不限制目標對象的數量,而一對一的關係則會把目標對象的數量限定爲一個。

Delete規則

在配置的時候必定要注意Delete Rule。當咱們刪除某個對象時,該規則決定了與之相關的那些對象因該如何處理。可供選擇的Delete規則有下面幾種:

Nullify

大多數時候均可以採用這種默認的刪除規則。若是刪除了某一個對象,而該對象與其它對象的關係有受制於Nullify規則,那麼這些對象就會把指向該對象的關係清空。

Cascade

這種刪除規則會沿着關係來傳播刪除操做

Deny

若是尚有其它對象與某個對象關聯,那麼這種刪除規則會阻止開發者刪除該對象。

No Action

這是一種奇怪的刪除規則,它會致使對象圖處於不一致狀態。假如運用了這條刪除規則,那麼在刪除某個對象以後,開發者必須手動設置反向的關係,以確保它們都指向有效的對象。

只有在嘗試保存上下文的時候,系統纔會去檢查刪除規則是否生效,假若發生違規,則會產生 NSCocoaErrorDomain錯誤,他的錯誤代碼是1600,若是想解決這個錯誤,就要在刪除以前確保該對象能夠安全的移除。

數據驗證錯誤

在對象保存到持久化存儲區以前,它們必須經過驗證。假如某個對象未能經過驗證,那麼系統就會拋出domain爲NSCocoaErrorDomain的錯誤。

實體的繼承

與類同樣,實體也能夠繼承自父實體。這個功能有助於簡化數據模型。子實體會自動繼承父實體的各類屬性。在底層的SQLite存儲區裏,父-子體系中的實體都會存儲到同一張數據表裏。

若是不想令父實體實例化,那麼能夠將其標註爲抽象的。只有可以肯定父實體在代碼中毫無心義時,才應該啓用這個選項。

相關文章
相關標籤/搜索