iOS項(xiàng)目中CoreData的使用

一、iOS數(shù)據(jù)儲存方式


image

二硕并、簡介CoreData數(shù)據(jù)存儲
Core Data 是 iOS系統(tǒng)提供的數(shù)據(jù)存儲方式纳猪,和傳統(tǒng)的SQL相比:
-它無需寫SQL語句
-允許開發(fā)者用面向?qū)ο蟮姆绞讲僮鞔鎯?shù)據(jù)陋葡,它的實(shí)體類可以和table中的表結(jié)構(gòu)對應(yīng)
-可以通過謂詞指定查詢條件
-由于是蘋果的親兒子棋傍,在iOS系統(tǒng)上的性能很好救拉,蘋果也對它進(jìn)行了多次優(yōu)化
-蘋果官方應(yīng)用的數(shù)據(jù)存儲幾乎都使用 Core Data

項(xiàng)目中CoreData的嵌入

嵌入CoreData很簡單,如果是還未創(chuàng)建工程瘫拣,那么在創(chuàng)建工程時(shí)勾選上Use Core Data亿絮,工程就會(huì)自動(dòng)生成一個(gè)與工程名字相同的.xcdatamodeld文件,以及在AppDelegate文件中自動(dòng)生成相應(yīng)代碼麸拄。


WX20181118-102146@2x.png

如果已經(jīng)創(chuàng)建了工程也不要緊派昧,command + n找到Data Model并創(chuàng)建,創(chuàng)建的名字最好與工程名相同拢切,否則可能會(huì)出現(xiàn)未知錯(cuò)誤蒂萎,不過作為例子我這里就隨便起一個(gè)了。


image

創(chuàng)建完成后在文件目錄中會(huì)多出一個(gè).xcdatamodeld文件淮椰,現(xiàn)在先不忙管它五慈,進(jìn)入AppDelegate文件,import CoreData并添加相關(guān)代碼,NSPersistentContainer(name:)中的參數(shù)必須與工程名一致,完事后如下:

import UIKit
import CoreData

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    // MARK: - Core Data stack
    
    lazy var persistentContainer: NSPersistentContainer = {
        /*
         The persistent container for the application. This implementation
         creates and returns a container, having loaded the store for the
         application to it. This property is optional since there are legitimate
         error conditions that could cause the creation of the store to fail.
         */
        let container = NSPersistentContainer(name: "TestCoreData")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                
                /*
                 Typical reasons for an error here include:
                 * The parent directory does not exist, cannot be created, or disallows writing.
                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                 * The device is out of space.
                 * The store could not be migrated to the current model version.
                 Check the error message to determine what the actual problem was.
                 */
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()
    
    // MARK: - Core Data Saving support
    
    func saveContext () {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }
}

這樣下來实苞,CoreData就成功導(dǎo)入到工程中了豺撑。
但是這一坨代碼寫到AppDelegate里面不太雅觀,出于“誰的事情誰來干”的原則黔牵,我們可以新建一個(gè)類,名為CoreDataStack.swift爷肝,把這一堆東西都移到新建的文件里面去猾浦。

CoreData的使用

CoreData為我們提供基本數(shù)據(jù)類型存儲,可供選擇的選項(xiàng)有14個(gè)灯抛,我這里就不一一列舉金赦,下文會(huì)有一張圖能看到支持的類型。雖然只有14個(gè)選項(xiàng)对嚼,但是在我看來夹抗,CoreData是沒有什么數(shù)據(jù)不能存儲的,因?yàn)橛袀€(gè)選項(xiàng)是Transformable纵竖,從字面意思就知道這個(gè)是可以轉(zhuǎn)換的類型漠烧,從代碼中用option可以查到它顯示的類型是NSObject杏愤,這就很好辦了,iOS中的所有對象都繼承自NSObject已脓,那我就可以將任意類型的數(shù)據(jù)轉(zhuǎn)為NSObject再存儲了珊楼,不過在轉(zhuǎn)之前要注意:數(shù)據(jù)類型必須遵守NSCoding協(xié)議,這也是CoreData最大的詬病度液,需要自己實(shí)現(xiàn)協(xié)議中的encode和decode方法厕宗,如果模型有很多屬性,就需要多寫很多代碼堕担。

創(chuàng)建模型

找到之前的.xcdatamodeld文件并打開已慢,選擇Add Entity創(chuàng)建一個(gè)模型并取名,我這里取作SysUser,右側(cè)第一欄Attributes就是模型的屬性了霹购,可以選擇模型屬性類型佑惠。
這是我們新建的一個(gè)SysUser的model:


WX20181117-205847@2x.png

簡單的創(chuàng)建幾個(gè)屬性,因?yàn)镃oreData不存在主鍵一說厕鹃,所以自己設(shè)置一個(gè)id屬性作為主鍵兢仰,這個(gè)id的唯一性由開發(fā)者自己保證。

增加數(shù)據(jù)

CoreData增加數(shù)據(jù)
首先要獲得一個(gè)context(上下文對象)剂碴,還記得我們上面說過的那個(gè)CoreDataStack.swift文件嗎把将,它里面的代碼應(yīng)該是這樣的:

import Foundation
import CoreData
class CoreDataStack: NSObject {
/**
創(chuàng)建單例
*/
    static let shared = CoreDataStack()
 lazy var documentDir: URL = {
        let documentDir = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first
        return documentDir!
    }()
    //獲取上下文
    lazy var context: NSManagedObjectContext = {
        let context = NSManagedObjectContext.init(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
        context.persistentStoreCoordinator = persistentStoreCoordinator
        return context
    }()
    // 存儲數(shù)據(jù)
    func saveContext() {
        do {
            try context.save()
        } catch {
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
   
    // MARK: - Core Data stack
    
    lazy var persistentContainer: NSPersistentContainer = {
        /*
         The persistent container for the application. This implementation
         creates and returns a container, having loaded the store for the
         application to it. This property is optional since there are legitimate
         error conditions that could cause the creation of the store to fail.
         */
        let container = NSPersistentContainer(name: "LeavesVideo")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                
                /*
                 Typical reasons for an error here include:
                 * The parent directory does not exist, cannot be created, or disallows writing.
                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                 * The device is out of space.
                 * The store could not be migrated to the current model version.
                 Check the error message to determine what the actual problem was.
                 */
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()
    
    
    lazy var managedObjectModel: NSManagedObjectModel = {
        let modelURL = Bundle.main.url(forResource: "LeavesVideo", withExtension: "momd")
        let managedObjectModel = NSManagedObjectModel.init(contentsOf: modelURL!)
        return managedObjectModel!
    }()
    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        let persistentStoreCoordinator = NSPersistentStoreCoordinator.init(managedObjectModel: managedObjectModel)
        let sqliteURL = documentDir.appendingPathComponent("LeavesVideo.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
    }()
}

這樣我們就可以調(diào)用

class func getContext()->NSManagedObjectContext {
        return CoreDataStack.shared.context
    }

獲取到上下文。

/**添加用戶*/
    class func insertUser(user:User){
        let person = NSEntityDescription.insertNewObject(forEntityName: "SysUser", into: UserUtil.getContext()) as! SysUser
        person.nickName = user.nickName
        person.icon = user.icon
        person.token = user.token
        person.id = user.id
        CoreDataStack.shared.saveContext()
    }

/**獲取用戶*/
    class func getCurrentUser()->SysUser{
        do {
            let results:[SysUser] = try UserUtil.getContext().fetch(SysUser.fatchUserRequest()) as! [SysUser]
            return results[0]
        } catch {
            fatalError();
        }
    }

**更新用戶的昵稱*/
    class func updateUserNickName(name:String){
        do {
            // 拿到符合條件的所有數(shù)據(jù)
            let result:SysUser = try UserUtil.getContext().fetch(SysUser.fatchUserRequest())[0] as! SysUser
            result.nickName = name
        } catch {
            fatalError();
        }
        CoreDataStack.shared.saveContext()
    }

/**刪除用戶*/
    class func deleteUser(){
        //先查詢數(shù)據(jù)是否存在
        do {
            let results:[SysUser] = try UserUtil.getContext().fetch(UserUtil.fatchUserRequest()) as! [SysUser]
            if results.isEmpty == false{
               // 刪除所有數(shù)據(jù)
                  UserUtil.getContext().delete(result[0])
                  CoreDataStack.shared.saveContext()
              }
        } catch {
            fatalError();
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末忆矛,一起剝皮案震驚了整個(gè)濱河市察蹲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌催训,老刑警劉巖洽议,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異漫拭,居然都是意外死亡亚兄,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門采驻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來审胚,“玉大人,你說我怎么就攤上這事礼旅∩胚叮” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵痘系,是天一觀的道長菲嘴。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么龄坪? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任昭雌,我火速辦了婚禮,結(jié)果婚禮上悉默,老公的妹妹穿的比我還像新娘城豁。我一直安慰自己,他們只是感情好抄课,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布唱星。 她就那樣靜靜地躺著,像睡著了一般跟磨。 火紅的嫁衣襯著肌膚如雪间聊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天抵拘,我揣著相機(jī)與錄音哎榴,去河邊找鬼。 笑死僵蛛,一個(gè)胖子當(dāng)著我的面吹牛尚蝌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播充尉,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼飘言,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了驼侠?” 一聲冷哼從身側(cè)響起姿鸿,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎倒源,沒想到半個(gè)月后苛预,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡笋熬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年热某,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胳螟。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡苫拍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出旺隙,到底是詐尸還是另有隱情,我是刑警寧澤骏令,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布蔬捷,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏周拐。R本人自食惡果不足惜铡俐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望妥粟。 院中可真熱鬧审丘,春花似錦、人聲如沸勾给。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽播急。三九已至脓钾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間桩警,已是汗流浹背可训。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捶枢,地道東北人握截。 一個(gè)月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像烂叔,于是被迫代替她去往敵國和親谨胞。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,321評論 8 265
  • 1长已、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明先生_x閱讀 15,968評論 3 119
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,089評論 1 32
  • 忘了注冊過簡書畜眨,今兒查GNMT才想起來,用戶名居然叫“和枝”术瓮。 既然注冊了康聂,那就寫點(diǎn)兒什么罷……
    Gottfried閱讀 187評論 0 1
  • __記頭馬領(lǐng)袖俱樂部第161次會(huì)議感受 一提到《我們不一樣》,我馬上就會(huì)哼唱出那句熟悉的歌詞:我們不一...
    無題的小倩閱讀 1,300評論 0 1