Swift实现CoreData存储数据

以前写过一篇介绍iOS数据存储方法的文章,包含:FMDB,SQLite3 ,Core Data,Plist,偏好设置,归档。 连接:www.jianshu.com/p/e88880be7…git

本文则是介绍Swift中CoreData的基本使用。
文中示例代码GitHub地址:Demogithub

coredata.gif

目录

1、 图形化建立模型
2、 手动建立模型并实现AppDelegate中的代码
3、 建立并实现CoreDataManagersql

1、图形化建立模型(这一小节的内容个人另外一篇文中也有,如已经熟悉,或想要直接手动建立模型,能够直接看第二小节正式进入Swift)

建立项目的时候,勾选下图中的Use Core Data选项,工程中会自动建立一个数据模型文件。固然,你也能够在开发中本身手动建立。编程

自动建立模型文件

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

建立出来的文件

若是没有勾选,也能够在这里手动建立。数组

手动建立

点击Add Entity以后,至关一张数据表。表的名称本身在上方定义,注意首字母要大写。 在界面中还能够为数据实体添加属性和关联属性。app

建立一个数据表

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

数据类型

编译以后,Xcode会自动生成Person的实体代码文件,而且文件不会显示在工程中,若是下图中右侧Codegen选择Manual/None,则Xcode就不会自动生成代码,咱们能够本身手动生成。编程语言

6.png

  • 手动生成实体类代码,选中CoreDataTest.xcdatamodeld文件,而后在Mac菜单栏中选择Editor,以下图所示。一路Next就能够了。
  • 若是没有选择Manual/None,依然进行手动建立的话,则会与系统自动建立的文件发生冲突,这点须要注意。
  • 你也能够不要选择Manual/None,直接使用系统建立好的NSManagedObject,一样会有4个文件,只是在工程中是看不到的。

手动建立NSManagedObject

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

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

编程语言

2、手动建立模型并实现AppDelegate中的代码

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

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

    建立模型.png

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

建立数据表.png

  1. 配置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!
    }()
复制代码
  1. 懒加载持久化存储协调器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!
    }()
复制代码
  1. 懒加载NSManagedObjectContext
lazy var context: NSManagedObjectContext = {
        let context = NSManagedObjectContext.init(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
        context.persistentStoreCoordinator = persistentStoreCoordinator
        return context
    }()
复制代码

3、建立并实现CoreDataManager

我通常是把数据存储方法封装到一个CoreDataManager中,这样在之后的使用中比较方便。固然,你也能够根据本身的需求灵活运用。

  1. 建立一个继承自NSObjectCoreDataManager.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
    }()
复制代码
  1. 实现更新数据的方法

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

// 更新数据
    private func saveContext() {
        do {
            try context.save()
        } catch {
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
复制代码
  1. 增长数据(保存数据)
  • 首先运用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()
    }
复制代码
  1. 获取全部数据
  • 若是是经过系统自动生成的CoreData文件,Person会自带一个fetchRequest()的方法,咱们能够直接经过Person.fetchRequest()的方式拿到personNSFetchRequest对象
  • 而后经过contextfetch(fetchRequest)方法拿到数据数组
// 获取全部数据
    func getAllPerson() -> [Person] {
        let fetchRequest: NSFetchRequest = Person.fetchRequest()
        do {
            let result = try context.fetch(fetchRequest)
            return result
        } catch {
            fatalError();
        }
    }
复制代码
  1. 获取特定条件的数据
  • 能够利用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();
        }
    }
复制代码
  1. 修改数据
  • 首先获取到想要修改的数据
  • 而后循环修改就能够了
  • 最后别忘记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()
    }
复制代码
  1. 根据条件删除数据
  • 与修改数据同样,首先拿到符合删除条件的数据
  • 循环调用contextdelete()方法就能够了
  • 最后别忘记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()
    }
复制代码
  1. 删除全部数据
  • 获取全部数据
  • 循环删除
  • save
// 删除全部数据
    func deleteAllPerson() {
        // 这里直接调用上面获取全部数据的方法
        let result = getAllPerson()
        // 循环删除全部数据
        for person in result {
            context.delete(person)
        }
        saveContext()
    }
复制代码

后记

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

本文Demo:github.com/remember17/…
做者GitHub:github.com/remember17

相关文章
相关标签/搜索