Core Data入门
在iOS App中,如果要存储的数据量比较大,就会使用Core Data。这里汇总了下使用Core Data的基本方式。
- 添加Core Data
- 配置Core Data中的Entity
- 添加新数据
- 读取与修改数据
- 使用NSPredicate筛选数据
- 删除数据
- 保存数据
- 一份NSPredicate使用备忘清单
添加Core Data
如果在创建项目时没有勾选Using Core Data,可以手动创建Core Data。手动创建Core Data的方式如下:
- 在项目中创建新的文件,类型为:Core Data。
- 添加相关的预设方法进入
AppDelegate
中,相关方法如下:
func applicationWillTerminate(_ application: UIApplication) {
self.saveContext()
}
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "DataModel")
container.loadPersistentStores(completionHandler: {
(storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
这两个方法是Xcode为使用Core Data的新项目自动创建的,我这里只是拷贝了进来。
配置Core Data中的Entity
点击创建的Core Data文件,我们在界面中配置Entity。Core Data中的Entity,就相当于编程语言中的Class,类比数据库就是一个Table。Entity的Attribute,就是Class的Property,Table中的Field。
举个例子: 我的To-do App中需要两个类,一个是Category,代表清单的类别;一个是Item,代表清单中的具体事项。
在Core Data中创建2个Entity分别是Category和Item。Category设置1个Attribute:name,类型为String;Item设置2个Attribute:title和done,分别是String和Bool类型。
然后配置Category和Item的关系,将Category对Item的关系设置为一对多,而Item对Category的关系设置为一对一,毕竟一个事项只有一个类别。
添加新数据
无论要对Core Data做什么,都需要用到context
,因此需要在用到Core Data的类中添加一个实例变量:
let context = (UIApplication.shared.delegate
as! AppDelegate).persistentContainer.viewContext
我要添加一个新的Category,那么从Core Data的Entity中创建对象是这样的:
let newCategory = Category(context: self.context) // 用Core Data中的Entity创建对象
newCategory.name = "Work" // 设置Entity对象的必要attribute
// 将新的category对象加入categoryList,而categoryList则指向是从数据库中读取的数据。
categoryList.append(newCategory)
读取与修改数据
从Core Data中读取全部数据:
func fetchData() {
let request: NSFetchRequest<Category> = Category.fetchRequest()
do {
// 将实例变量categoryList指向读取的数据
categoryList = try context.fetch(request)
} catch {
print("Error fetching request, \(error)")
}
}
而要修改数据,则可以选择使用以下两种方式之一:
// 将刚加入的Work改为Shopping
categoryList[0].name = "Shopping"
// 将刚才的Shopping category的name attribute改为"Chores"
categoryList[0].setValue("Chores", forKey: "name")
使用Predicate筛选数据
有时我们不需要读取数据库中的所有数据,比如我只想读取:Category是Work的所有待办事项Item;或者我想搜索Work类别里待办事项中名字里包含"urgent"的事项,这时,我们这样写:
let selectedCategory = "Work" // 清单类别
let searchKeyword = "urgent" // 搜索筛选的关键词
let request: NSFetchRequest<Item> = Item.fetchRequest()
// 此处parentCategory是Core Data中Item的一个关系设定,将关系指向Category并命名为parentCategory。
let predicate1 = NSPredicate(format: "parentCategory.name MATCHES %@", selectedCategory)
let predicate2 = NSPredicate(format: "title CONTAINS[cd] %@", searchKeyword)
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1, predicate2])
request.predicate = compoundPredicate
request.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)]
do {
self.selectedItems = try context.fetch(request)
} catch {
print("Error fetching data, \(error)")
}
删除数据
读取数据后,直接从指向数据的变量中,删除对应的数据即可。
self.context.delete(selectedItems[1]) // 从数据中移除
selectedItems.remove(at: 1) // 接着更新下指向数据的实例变量
保存数据
对Core Data进行新增、修改、删除后,都要进行保存才能生效。
do {
try context.save()
} catch {
print("Error saving data, \(error)")
}
NSPredicate使用备忘
关于Predicate的一份备忘清单,可以随时查看:NSPredicate备忘清单