iOS项目中CoreData的使用

一、iOS数据储存方式


image

二、简介CoreData数据存储
Core Data 是 iOS系统提供的数据存储方式,和传统的SQL相比:
-它无需写SQL语句
-允许开发者用面向对象的方式操作存储数据,它的实体类可以和table中的表结构对应
-可以通过谓词指定查询条件
-由于是苹果的亲儿子,在iOS系统上的性能很好,苹果也对它进行了多次优化
-苹果官方应用的数据存储几乎都使用 Core Data

项目中CoreData的嵌入

嵌入CoreData很简单,如果是还未创建工程,那么在创建工程时勾选上Use Core Data,工程就会自动生成一个与工程名字相同的.xcdatamodeld文件,以及在AppDelegate文件中自动生成相应代码。


WX20181118-102146@2x.png

如果已经创建了工程也不要紧,command + n找到Data Model并创建,创建的名字最好与工程名相同,否则可能会出现未知错误,不过作为例子我这里就随便起一个了。


image

创建完成后在文件目录中会多出一个.xcdatamodeld文件,现在先不忙管它,进入AppDelegate文件,import CoreData并添加相关代码,NSPersistentContainer(name:)中的参数必须与工程名一致,完事后如下:

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就成功导入到工程中了。
但是这一坨代码写到AppDelegate里面不太雅观,出于“谁的事情谁来干”的原则,我们可以新建一个类,名为CoreDataStack.swift,把这一堆东西都移到新建的文件里面去。

CoreData的使用

CoreData为我们提供基本数据类型存储,可供选择的选项有14个,我这里就不一一列举,下文会有一张图能看到支持的类型。虽然只有14个选项,但是在我看来,CoreData是没有什么数据不能存储的,因为有个选项是Transformable,从字面意思就知道这个是可以转换的类型,从代码中用option可以查到它显示的类型是NSObject,这就很好办了,iOS中的所有对象都继承自NSObject,那我就可以将任意类型的数据转为NSObject再存储了,不过在转之前要注意:数据类型必须遵守NSCoding协议,这也是CoreData最大的诟病,需要自己实现协议中的encode和decode方法,如果模型有很多属性,就需要多写很多代码。

创建模型

找到之前的.xcdatamodeld文件并打开,选择Add Entity创建一个模型并取名,我这里取作SysUser,右侧第一栏Attributes就是模型的属性了,可以选择模型属性类型。
这是我们新建的一个SysUser的model:


WX20181117-205847@2x.png

简单的创建几个属性,因为CoreData不存在主键一说,所以自己设置一个id属性作为主键,这个id的唯一性由开发者自己保证。

增加数据

CoreData增加数据
首先要获得一个context(上下文对象),还记得我们上面说过的那个CoreDataStack.swift文件吗,它里面的代码应该是这样的:

import Foundation
import CoreData
class CoreDataStack: NSObject {
/**
创建单例
*/
    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
    }()
    // 存储数据
    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
    }()
}

这样我们就可以调用

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 {
            // 拿到符合条件的所有数据
            let result:SysUser = try UserUtil.getContext().fetch(SysUser.fatchUserRequest())[0] as! SysUser
            result.nickName = name
        } catch {
            fatalError();
        }
        CoreDataStack.shared.saveContext()
    }

/**删除用户*/
    class func deleteUser(){
        //先查询数据是否存在
        do {
            let results:[SysUser] = try UserUtil.getContext().fetch(UserUtil.fatchUserRequest()) as! [SysUser]
            if results.isEmpty == false{
               // 删除所有数据
                  UserUtil.getContext().delete(result[0])
                  CoreDataStack.shared.saveContext()
              }
        } catch {
            fatalError();
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,340评论 8 265
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,969评论 3 119
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,093评论 1 32
  • 忘了注册过简书,今儿查GNMT才想起来,用户名居然叫“和枝”。 既然注册了,那就写点儿什么罢……
    Gottfried阅读 191评论 0 1
  • __记头马领袖俱乐部第161次会议感受 一提到《我们不一样》,我马上就会哼唱出那句熟悉的歌词:我们不一...
    无题的小倩阅读 1,306评论 0 1