Core Data 是什么样子的

栏目: 数据库 · 发布时间: 5年前

内容简介: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 是什么

Core Data 是一个模型层的技术,帮助开发者建立代表程序状态的模型层。同时也是一种持久化技术,它能将模型对象的状态持久化到磁盘。它是完全独立于 UI 层级的框架,是作为模型层框架被设计出来的。

Core Data 不是一个 O/RM,但它比 O/RM 能做的更多。它也不是一个 SQL wrapper。它默认使用 SQL,但它是一种更高级的抽象概念。

堆栈

Core Data 有相当多可用的组件。当所有的组件都捆绑到一起的时候,我们把它称作 Core Data 堆栈,这个堆栈有两个主要部分。

一部分是关于对象图管理,这正是你需要很好掌握的那一部分,并且知道怎么使用。 另一部分是关于持久化,比如,保存你模型对象的状态,然后再恢复模型对象的状态。

堆栈结构如下

Core Data 是什么样子的

NSPersistentStoreCoordinator 是一个位于本地存储文件与缓存层(NSManagedObjectContext)之间的一个持久化层,它是真实操作数据库本地文件。

NSManagedObjectContext 是一个被管理数据的上下文,它实际上是对所有数据库操作的一个缓存层,把所有的操作都先缓存起来避免大量磁盘 IO 造成不流畅,在操作完数据库后调用其 save 方法,就可以把数据库操作提交给持久化层(NSPersistentStoreCoordinator),由持久化层一次性写入数据库文件。

NSManagedObject 是被管理的数据记录,对应数据库的一个表。

另外,Core Data 可以将多个 stores 附属于同一个持久化存储协调器,并且除了存储 SQL 格式外,还有很多存储类型可供选择。 最常见的方案如下

Core Data 是什么样子的

实际使用

下面是笔者定义的一个 Event 表的元素组成

Core Data 是什么样子的

定义数据模型

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 官方很久之前就已经推出,但是并不受开发者青睐。笔者在这段时间的学习过程中也在思考这个问题。

下面是笔者学习中遇到的注意点:

  1. Core Data 中没有自增数据类型。因为 Core Data 不能使用数据库思维去使用,所以也就很好解释了。
  2. 设置 context 的 merge 策略,减少数据迁移的麻烦。
  3. 最好使用多线程,可以进一步提升性能。

最后,文章开头给出了性能比较。但是,笔者认为,在客户端并没有很大量的数据写入,只要开发者在使用过程中稍作注意,性能应该不是否决 Core Data 技术方案的理由。反倒,Core Data 对 iCloud 很好的支持,以及数据迁移备份,这些都可以很容易实现。笔者认为,完全可以考虑使用它做客户端的数据持久化方案。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Agile Web Development with Rails, Third Edition

Agile Web Development with Rails, Third Edition

Sam Ruby、Dave Thomas、David Heinemeier Hansson / Pragmatic Bookshelf / 2009-03-17 / USD 43.95

Rails just keeps on changing. Rails 2, released in 2008, brings hundreds of improvements, including new support for RESTful applications, new generator options, and so on. And, as importantly, we’ve a......一起来看看 《Agile Web Development with Rails, Third Edition》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试