Core Data入门

在iOS App中,如果要存储的数据量比较大,就会使用Core Data。这里汇总了下使用Core Data的基本方式。

  1. 添加Core Data
  2. 配置Core Data中的Entity
  3. 添加新数据
  4. 读取与修改数据
  5. 使用NSPredicate筛选数据
  6. 删除数据
  7. 保存数据
  8. 一份NSPredicate使用备忘清单

添加Core Data

如果在创建项目时没有勾选Using Core Data,可以手动创建Core Data。手动创建Core Data的方式如下:

  1. 在项目中创建新的文件,类型为:Core Data。
  2. 添加相关的预设方法进入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备忘清单


comments powered by Disqus