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,工程就會自動生成一個(gè)與工程名字相同的.xcdatamodeld文件,以及在AppDelegate文件中自動生成相應(yīng)代碼。


WX20181118-102146@2x.png

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


image

創(chuàng)建完成后在文件目錄中會多出一個(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è),我這里就不一一列舉,下文會有一張圖能看到支持的類型。雖然只有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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容