使用 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 模型之后,往往会编译出各种奇怪的错误,这时候,只需要把数据结构截图,删除重新建一份即可解决


KyleBing
659 声望18 粉丝

前端,喜欢 Javascript scss,喜欢做一些实用的小工具