使用 CoreData

1. 新建项目时选用 core data

或者在后来添加 ​​.xcdatamodeld​​ 文件

2. 在 AppDelegate 中 获取 persistentContainer

  1. 声明一个​​lazy​​​ 变量​​persistentContainer​
  2. 把模型名字传递给初始化的方法
  3. 如果存在 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​​ 模型之后,往往会编译出各种奇怪的错误,这时候,只需要把数据结构截图,删除重新建一份即可解决