内容简介:Core Data 是 iOS3.0 时引入的一个数据持久化的框架。与 sqlite 对比最大的优点莫过于支持对象的存储,苹果的官方文档说其简化了数据库的操作,使用 Core Data 确实可以大量减少代码中的 SQL 语句。可是现状,大家对于持久化的选择方案仍多数是 FMDB。笔者猜测,最大的原因可能就是性能。Core Data 是一个模型层的技术,帮助开发者建立代表程序状态的模型层。同时也是一种持久化技术,它能将模型对象的状态持久化到磁盘。它是完全独立于 UI 层级的框架,是作为模型层框架被设计出来的。
Core Data 是 iOS3.0 时引入的一个数据持久化的框架。与 sqlite 对比最大的优点莫过于支持对象的存储,苹果的官方文档说其简化了数据库的操作,使用 Core Data 确实可以大量减少代码中的 SQL 语句。
可是现状,大家对于持久化的选择方案仍多数是 FMDB。笔者猜测,最大的原因可能就是性能。
Core Data 是什么
Core Data 是一个模型层的技术,帮助开发者建立代表程序状态的模型层。同时也是一种持久化技术,它能将模型对象的状态持久化到磁盘。它是完全独立于 UI 层级的框架,是作为模型层框架被设计出来的。
Core Data 不是一个 O/RM,但它比 O/RM 能做的更多。它也不是一个 SQL wrapper。它默认使用 SQL,但它是一种更高级的抽象概念。
堆栈
Core Data 有相当多可用的组件。当所有的组件都捆绑到一起的时候,我们把它称作 Core Data 堆栈,这个堆栈有两个主要部分。
一部分是关于对象图管理,这正是你需要很好掌握的那一部分,并且知道怎么使用。 另一部分是关于持久化,比如,保存你模型对象的状态,然后再恢复模型对象的状态。
堆栈结构如下
NSPersistentStoreCoordinator 是一个位于本地存储文件与缓存层(NSManagedObjectContext)之间的一个持久化层,它是真实操作数据库本地文件。
NSManagedObjectContext 是一个被管理数据的上下文,它实际上是对所有数据库操作的一个缓存层,把所有的操作都先缓存起来避免大量磁盘 IO 造成不流畅,在操作完数据库后调用其 save 方法,就可以把数据库操作提交给持久化层(NSPersistentStoreCoordinator),由持久化层一次性写入数据库文件。
NSManagedObject 是被管理的数据记录,对应数据库的一个表。
另外,Core Data 可以将多个 stores 附属于同一个持久化存储协调器,并且除了存储 SQL 格式外,还有很多存储类型可供选择。 最常见的方案如下
实际使用
下面是笔者定义的一个 Event 表的元素组成
定义数据模型
class MXWEventModel: NSObject { var id: Int64 var time: Date var title: String var detail: String var addr: String init(id: Int64, title: String, detail: String, addr: String, time: Date){} } 复制代码
新增数据
let context = persistentContainer.viewContext public func add(model: AnyObject) { let eventModel: MXWEventModel = model as! MXWEventModel let entity = NSEntityDescription.entity(forEntityName: @"MXWEvent", in: context!) let obj = NSManagedObject(entity: entity!, insertInto: context) obj.setValue(eventModel.id, forKey: "id") obj.setValue(eventModel.title, forKey: "title") obj.setValue(eventModel.detail, forKey: "detail") obj.setValue(eventModel.time, forKey: "time") obj.setValue(eventModel.addr, forKey: "addr") do { try context?.save() } catch { print(error) } } 复制代码
删除数据
public func delete(id: Int64) { let request = NSFetchRequest<NSFetchRequestResult>(entityName: @"MXWEvent") request.predicate = NSPredicate(format: "id==\(id)") let deleteRequest = NSBatchDeleteRequest(fetchRequest: request) do { try context?.execute(deleteRequest) } catch { print(error) } } 复制代码
修改数据
public func update(id: Int64, model: AnyObject) { let eventModel: MXWEventModel = model as! MXWEventModel let request = NSFetchRequest<NSFetchRequestResult>(entityName: @"MXWEvent") request.predicate = NSPredicate(format: "id==\(id)") do { let eventObj = try context?.fetch(request) let updateObj = eventObj?.first as! NSManagedObject updateObj.setValue(eventModel.title, forKey: "title") updateObj.setValue(eventModel.detail, forKey: "detail") updateObj.setValue(eventModel.time, forKey: "time") updateObj.setValue(eventModel.addr, forKey: "addr") do { try context?.save() } catch { print(error) } } catch { print(error) } } 复制代码
查找数据
public func fetch(id: Int64) -> AnyObject? { let request = NSFetchRequest<NSFetchRequestResult>(entityName: @"MXWEvent") request.predicate = NSPredicate(format: "id==\(id)") do { let r = try context?.fetch(request) for data in r as! [NSManagedObject] { let m = MXWEventModel(id: data.value(forKey: "id") as! Int64, title: data.value(forKey: "title") as! String, detail: data.value(forKey: "detail") as! String, addr: data.value(forKey: "addr") as! String, time: data.value(forKey: "time") as! Date) return m } } catch { print(error) } } 复制代码
高级功能
数据迁移
在功能迭代过程中,难免会遇到要修改 .xcdatamodeld
文件。例如,新增或删除一个实体、增加或删除一个原有实体的属性等。如果开发者没有设置数据迁移,那更新后原有的数据将会被清空,所以此时需要进行数据的迁移操作。
Core Data 可以设置轻量级的数据迁移,系统会自动分析差异,进行映射,这种方式只适用于简单的增删实体或是增删属性等操作。除此之外还有一种相当复杂的自定义数据迁移。
// MARK: - Core Data stack lazy var persistentContainer: NSPersistentContainer = { let container = NSPersistentContainer(name: "Demo") container.loadPersistentStores(completionHandler: { storeDescription, error in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } // 设置数据迁移(shouldMigrateStoreAutomatically 默认值为 true) if let sDescription: NSPersistentStoreDescription = storeDescription as NSPersistentStoreDescription { sDescription.shouldMigrateStoreAutomatically = true sDescription.shouldInferMappingModelAutomatically = false } }) return container }() 复制代码
思考
对于 Core Data,Apple 官方很久之前就已经推出,但是并不受开发者青睐。笔者在这段时间的学习过程中也在思考这个问题。
下面是笔者学习中遇到的注意点:
- Core Data 中没有自增数据类型。因为 Core Data 不能使用数据库思维去使用,所以也就很好解释了。
- 设置 context 的 merge 策略,减少数据迁移的麻烦。
- 最好使用多线程,可以进一步提升性能。
最后,文章开头给出了性能比较。但是,笔者认为,在客户端并没有很大量的数据写入,只要开发者在使用过程中稍作注意,性能应该不是否决 Core Data 技术方案的理由。反倒,Core Data 对 iCloud 很好的支持,以及数据迁移备份,这些都可以很容易实现。笔者认为,完全可以考虑使用它做客户端的数据持久化方案。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Linux 进程在内核眼中是什么样子的?
- 真正的程序员到底是什么样子的?
- 懂程序员的产品经理是什么样子?
- 你见过的 “垃圾” 项目是这样子么?
- 他活成了多数程序员羡慕的样子......
- Java 对象在虚拟机中到底是什么样子?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。