Swift实现CoreData存储数据

2018 年 1 月 30 日 CocoaChina

之前写过一篇介绍iOS数据存储方法的文章,包含:FMDB,SQLite3 ,Core Data,Plist,偏好设置,归档。


链接:https://www.jianshu.com/p/e88880be794f


本文则是介绍Swift中CoreData的基本使用。

文中示例代码GitHub地址:Demo


coredata.gif


目录


一、 图形化创建模型

二、 手动创建模型并实现AppDelegate中的代码

三、 创建并实现CoreDataManager


一、图形化创建模型(这一小节的内容我的另一篇文中也有,如已经熟悉,或想要直接手动创建模型,可以直接看第二小节正式进入Swift)


创建项目的时候,勾选下图中的Use Core Data选项,工程中会自动创建一个数据模型文件。当然,你也可以在开发中自己手动创建。


自动创建模型文件


下图就是自动创建出来的文件


创建出来的文件


如果没有勾选,也可以在这里手动创建。


手动创建


点击Add Entity之后,相当一张数据表。表的名称自己在上方定义,注意首字母要大写。


在界面中还可以为数据实体添加属性和关联属性。


创建一个数据表


Core Data属性支持的数据类型如下


数据类型


编译之后,Xcode会自动生成Person的实体代码文件,并且文件不会显示在工程中,如果下图中右侧Codegen选择Manual/None,则Xcode就不会自动生成代码,我们可以自己手动生成。


6.png


  • 手动生成实体类代码,选中CoreDataTest.xcdatamodeld文件,然后在Mac菜单栏中选择Editor,如下图所示。一路Next就可以了。

  • 如果没有选择Manual/None,依然进行手动创建的话,则会与系统自动创建的文件发生冲突,这点需要注意。

  • 你也可以不要选择Manual/None,直接使用系统创建好的NSManagedObject,同样会有4个文件,只是在工程中是看不到的。


手动创建NSManagedObject


Swift中手动创建出来的是这样2个文件



还要注意编程语言的选择,Swift或OC


编程语言


二、手动创建模型并实现AppDelegate中的代码


讲道理,这一节应该是Core Data堆栈的介绍与使用,不过由于之前的文章中已经有了,这里就不啰嗦了,我们直接上图和代码。


1.如下图所示,创建模型,我这里直接创建一个命名为Model的模型。


创建模型.png


2.创建Person表,两个属性name和age,注意右侧的Codegen我们这里选择Class Definition,然后直接Command+B编译代码,Xcode会自动帮我们生成Person+CoreDataClass.swift和Person+CoreDataProperties.swift文件


创建数据表.png


3.配置AppDelegate中的代码,首先导入CoreData头文件,然后懒加载NSManagedObjectModel


注意modelURL中填写的是模型文件的名字,并且后缀填写momd


    import CoreData


    lazy var managedObjectModel: NSManagedObjectModel = {

        let modelURL = Bundle.main.url(forResource: "Model", withExtension: "momd")

        let managedObjectModel = NSManagedObjectModel.init(contentsOf: modelURL!)

        return managedObjectModel!

    }()


4.懒加载持久化存储协调器NSPersistentStoreCoordinator


  • sqliteURL是sqlite文件的路径

  • documentDir是后面加载好了的Document路径


    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {

        let persistentStoreCoordinator = NSPersistentStoreCoordinator.init(managedObjectModel: managedObjectModel)

        let sqliteURL = documentDir.appendingPathComponent("Model.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

    }()


    lazy var documentDir: URL = {

        let documentDir = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first

        return documentDir!

    }()


5.懒加载NSManagedObjectContext


    lazy var context: NSManagedObjectContext = {

        let context = NSManagedObjectContext.init(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)

        context.persistentStoreCoordinator = persistentStoreCoordinator

        return context

    }()


三、创建并实现CoreDataManager


我一般是把数据存储方法封装到一个CoreDataManager中,这样在以后的使用中比较方便。当然,你也可以根据自己的需求灵活运用。


1.创建一个继承自NSObject的CoreDataManager.swfit文件,并且import CoreData


创建CoreDataManager


2.实现CoreDataManager的单例,并且拿到AppDelegate中刚才懒加载的NSManagedObjectContext


swift中创建单例比较方便,直接static let shared = CoreDataManager()


    // 单例

    static let shared = CoreDataManager()

    

    // 拿到AppDelegate中创建好了的NSManagedObjectContext

    lazy var context: NSManagedObjectContext = {

        let context = ((UIApplication.shared.delegate) as! AppDelegate).context

        return context

    }()


3.实现更新数据的方法


除了查询数据,其余对数据进行增删改的时候,都别忘记调用这个方法,只有这个方法执行ok,才算增删改完成。


    // 更新数据

    private func saveContext() {

        do {

            try context.save()

        } catch {

            let nserror = error as NSError

            fatalError("Unresolved error (nserror), (nserror.userInfo)")

        }

    }


4.增加数据(保存数据)


  • 首先运用NSEntityDescription创建出person

  • 然后为person赋值,最终调用saveContext()方法保存数据


    // 增加数据

    func savePersonWith(name: String, age: Int16) {

        let person = NSEntityDescription.insertNewObject(forEntityName: "Person", into: context) as! Person

        person.name = name

        person.age = age

        saveContext()

    }


5.获取所有数据


  • 如果是通过系统自动生成的CoreData文件,Person会自带一个fetchRequest()的方法,我们可以直接通过Person.fetchRequest()的方式拿到person的NSFetchRequest对象

  • 然后通过context的fetch(fetchRequest)方法拿到数据数组


    // 获取所有数据

    func getAllPerson() -> [Person] {

        let fetchRequest: NSFetchRequest = Person.fetchRequest()

        do {

            let result = try context.fetch(fetchRequest)

            return result

        } catch {

            fatalError();

        }

    }


6.获取特定条件的数据


  • 可以利用NSPredicate来过滤出符合一定条件的数据

  • 而NSFetchRequest中有predicate这样一个属性


    // 根据姓名获取数据

    func getPersonWith(name: String) -> [Person] {

        let fetchRequest: NSFetchRequest = Person.fetchRequest()

        fetchRequest.predicate = NSPredicate(format: "name == %@", name)

        do {

            let result: [Person] = try context.fetch(fetchRequest)

            return result

        } catch {

            fatalError();

        }

    }


7.修改数据


  • 首先获取到想要修改的数据

  • 然后循环修改就可以了

  • 最后别忘记save


    // 根据姓名修改数据

    func changePersonWith(name: String, newName: String, newAge: Int16) {

        let fetchRequest: NSFetchRequest = Person.fetchRequest()

        fetchRequest.predicate = NSPredicate(format: "name == %@", name)

        do {

            // 拿到符合条件的所有数据

            let result = try context.fetch(fetchRequest)

            for person in result {

                // 循环修改

                person.name = newName

                person.age = newAge

            }

        } catch {

            fatalError();

        }

        saveContext()

    }


8.根据条件删除数据


  • 与修改数据一样,首先拿到符合删除条件的数据

  • 循环调用context的delete()方法就可以了

  • 最后别忘记save


    // 根据姓名删除数据

    func deleteWith(name: String) {

        let fetchRequest: NSFetchRequest = Person.fetchRequest()

        fetchRequest.predicate = NSPredicate(format: "name == %@", name)

        do {

            let result = try context.fetch(fetchRequest)

            for person in result {

                context.delete(person)

            }

        } catch {

            fatalError();

        }

        saveContext()

    }


9.删除所有数据


  • 获取所有数据

  • 循环删除

  • save


    // 删除所有数据

    func deleteAllPerson() {

        // 这里直接调用上面获取所有数据的方法

        let result = getAllPerson()

        // 循环删除所有数据

        for person in result {

            context.delete(person)

        }

        saveContext()

    }




后记


本文运用一个简单的示例来说明swift中如何使用CoreData,更多用法或注意事项就不一一列举了。


本文Demo:

https://github.com/remember17/CoreDataSwiftDemo 

作者GitHub:

https://github.com/remember17


登录查看更多
0

相关内容

Core Data Programming Guide: Introduction to Core Data Programming Guide | Loading The Core Data framework provides generalized and automated solutions to common tasks associated with object life-cycle and object graph management, including persistence.
【2020新书】实战R语言4,323页pdf
专知会员服务
98+阅读 · 2020年7月1日
Python地理数据处理,362页pdf,Geoprocessing with Python
专知会员服务
110+阅读 · 2020年5月24日
【Manning新书】现代Java实战,592页pdf
专知会员服务
98+阅读 · 2020年5月22日
干净的数据:数据清洗入门与实践,204页pdf
专知会员服务
160+阅读 · 2020年5月14日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
115+阅读 · 2020年5月10日
Python分布式计算,171页pdf,Distributed Computing with Python
专知会员服务
105+阅读 · 2020年5月3日
Keras作者François Chollet推荐的开源图像搜索引擎项目Sis
专知会员服务
29+阅读 · 2019年10月17日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
如何用GitLab本地私有化部署代码库?
Python程序员
9+阅读 · 2018年12月29日
命名实体识别从数据集到算法实现
专知
55+阅读 · 2018年6月28日
Neo4j 和图数据库起步
Linux中国
8+阅读 · 2017年12月20日
无需一行代码就能搞定机器学习的开源神器
人工智能头条
6+阅读 · 2017年11月7日
python pandas 数据处理
Python技术博文
3+阅读 · 2017年8月30日
Arxiv
5+阅读 · 2018年5月1日
Arxiv
13+阅读 · 2018年4月18日
Arxiv
3+阅读 · 2012年11月20日
VIP会员
相关VIP内容
【2020新书】实战R语言4,323页pdf
专知会员服务
98+阅读 · 2020年7月1日
Python地理数据处理,362页pdf,Geoprocessing with Python
专知会员服务
110+阅读 · 2020年5月24日
【Manning新书】现代Java实战,592页pdf
专知会员服务
98+阅读 · 2020年5月22日
干净的数据:数据清洗入门与实践,204页pdf
专知会员服务
160+阅读 · 2020年5月14日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
115+阅读 · 2020年5月10日
Python分布式计算,171页pdf,Distributed Computing with Python
专知会员服务
105+阅读 · 2020年5月3日
Keras作者François Chollet推荐的开源图像搜索引擎项目Sis
专知会员服务
29+阅读 · 2019年10月17日
相关资讯
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
如何用GitLab本地私有化部署代码库?
Python程序员
9+阅读 · 2018年12月29日
命名实体识别从数据集到算法实现
专知
55+阅读 · 2018年6月28日
Neo4j 和图数据库起步
Linux中国
8+阅读 · 2017年12月20日
无需一行代码就能搞定机器学习的开源神器
人工智能头条
6+阅读 · 2017年11月7日
python pandas 数据处理
Python技术博文
3+阅读 · 2017年8月30日
Top
微信扫码咨询专知VIP会员