Core Data 是什么样子的

Core Data 是 iOS3.0 时引入的一个数据持久化的框架。与 sqlite 对比最大的优势莫过于支持对象的存储,苹果的官方文档说其简化了数据库的操做,使用 Core Data 确实能够大量减小代码中的 SQL 语句。sql

但是现状,你们对于持久化的选择方案仍多数是 FMDB。笔者猜想,最大的缘由可能就是性能。数据库

各类持久化方案性能比较

Core Data 是什么

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

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

堆栈

Core Data 有至关多可用的组件。当全部的组件都捆绑到一块儿的时候,咱们把它称做 Core Data 堆栈,这个堆栈有两个主要部分。多线程

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

堆栈结构以下框架

Core Data 堆栈

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

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

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

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

多个 stores 持久化

实际使用

下面是笔者定义的一个 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 官方好久以前就已经推出,可是并不受开发者青睐。笔者在这段时间的学习过程当中也在思考这个问题。

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

  1. Core Data 中没有自增数据类型。由于 Core Data 不能使用数据库思惟去使用,因此也就很好解释了。
  2. 设置 context 的 merge 策略,减小数据迁移的麻烦。
  3. 最好使用多线程,能够进一步提高性能。

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

参考文档

《Core Data Programming Guide》

相关文章
相关标签/搜索