使用 CoreData
1. 新建项目时选用 core data
或者在后来添加 .xcdatamodeld
文件
2. 在 AppDelegate 中 获取 persistentContainer
- 声明一个
lazy
变量persistentContainer
- 把模型名字传递给初始化的方法
- 如果存在 store 返回 store
class AppDelegate: UIResponder, UIApplicationDelegate {
...
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "DataModel")
container.loadPersistentStores { description, error in
if let error = error {
fatalError("Unable to load persistent stores: \(error)")
}
}
return container
}()
...
}
获取到 persistentContainer
之后,在这个 persistentContainer
中包含着:
- model:
managedObjectModel
- context:
viewContext
- store codrdinator:
persistentStoreCoordinator
3. 给 ViewController 传递 persistentContainer
1. 在 VC 中添加一个变量 container
class ViewController: UIViewController {
var container: NSPersistentContainer!
override func viewDidLoad() {
super.viewDidLoad()
guard container != nil else {
fatalError("This view needs a persistent container.")
}
// The persistent container is available.
}
}
2. 在 AppDelegate 中传递这个变量
在 AppDelegate
中,给应用的 rootViewController
传递
class AppDelegate: UIResponder, UIApplicationDelegate {
...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let rootVC = window?.rootViewController as? ViewController {
rootVC.container = persistentContainer
}
return true
}
...
}
如果想在其它 VC 中使用 container,重复上面的步骤,在目标 VC 中添加接收变量,在前一个 VC 中通过 prepare(for:sender:)
传递这个变量
class ViewController: UIViewController {
...
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let nextVC = segue.destination as? NextViewController {
nextVC.container = container
}
}
}
或者直接在 AppDelegate 中添加两个变量 :
static var persistentContainer: NSPersistentContainer{
return (UIApplication.shared.delegate as! AppDelegate).persistentContainer
}
static var viewContext: NSManagedObjectContext{
return persistentContainer.viewContext
4. 添加数据
添加 5 张卡片
for index in 1...5 {
let newCard = Card(context: context)
newCard.id = Int16(index)
newCard.idNumber = Date().timeIntervalSince1970.toString()
newCard.name = "card-\(index)"
newCard.type = String(CardTypes.BankCard)
newCard.dateInit = Date()
do {
try context.save()
} catch {
print("-----save Cards CoreData error")
}
}
5. 查询数据
var cards: Array<Card> = []
DispatchQueue.main.async { [unowned self] in
do {
try self.cards = self.context.fetch(Card.fetchRequest())
} catch {
print("Feth Card Data fail")
}
self.tableView.reloadData()
}
6. 修改数据
修改数据需要先获取到你查询到的数据,查询到的每个数据都是跟 context 有关联的。
如你像下面这样修改了你查询出来的某个元素,这个元素的
hasChanges
属性就会返回 true
, 此时只需要 context.save()
一下即可保存
card.name = "new Name"
if currentCard.hasChanges {
do {
try context.save()
} catch {
print("CoreData: save object error")
}
}
7. 很多错误的解决办法
很多时候在大改 CoreData
模型之后,往往会编译出各种奇怪的错误,这时候,只需要把数据结构截图,删除重新建一份即可解决