iOS開發(fā)筆記之Core Data(一)

CoreData 是 iOS3.0 時引入的一個數(shù)據(jù)持久化的框架。利用這個框架我們可以非常方便的對數(shù)據(jù)進行操作。
可以先從一個簡單的例子來看一下CoreData到底能干啥:

首先我們要新建一個單頁面項目,勾選選項CoreData;

屏幕快照 2016-10-20 上午11.50.34.png
屏幕快照 2016-10-20 上午11.49.09.png

然后在storyboard中拖一個tableView到ViewController上,并導入一個NavigationController,在導航欄上添加一個button(此處不是CoreData的重點所以我們簡單敘述),同時與代碼建立關聯(lián);

屏幕快照 2016-10-20 下午6.19.19.png
屏幕快照 2016-10-20 下午6.20.59.png
屏幕快照 2016-10-20 下午6.21.07.png

然后打開 項目名.xcdatamodeld,新建一個實體Person和一個實體的屬性name

![屏幕快照 2016-10-23 下午9.14.37_545952.png]
](http://upload-images.jianshu.io/upload_images/1830151-ef898efbe2c4719e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

屏幕快照 2016-10-23 下午9.14.37.png

現(xiàn)在開始實現(xiàn)功能,功能很簡單就是點擊添加按鈕添加一個name到表格中,數(shù)據(jù)在app退出后始終保存

ViewController.swift代碼如下:

import UIKit
import CoreData

class ViewController: UIViewController {

    @IBOutlet weak var tabelView:UITableView!
    
    @IBAction func addName(_ sender:UIBarButtonItem) {
        let alert = UIAlertController(title: "姓名", message: "請輸入姓名:", preferredStyle: .alert)
        let saveAction = UIAlertAction(title: "保存", style: .default) {
            [unowned self] action in
            guard let textField = alert.textFields?.first,
                let nameToSave = textField.text else {
                    return
            }
            self.save(name: nameToSave)
            self.tabelView.reloadData()
        }
        let cancelAction = UIAlertAction(title: "取消", style: .default)
        alert.addTextField()
        alert.addAction(saveAction)
        alert.addAction(cancelAction)
        present(alert,animated: true)
    }
    
    //var names:[String] = []
    
    var people:[NSManagedObject] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = "列表"
        tabelView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
        
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    override func viewWillAppear(_ animated: Bool) {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            return
        } //判斷appDelegate是否符合條件 符合的話就執(zhí)行下面的代碼 不符合直接return退出
        let manageContext = appDelegate.persistentContainer.viewContext
        let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Person")
        
        do {
            people = try manageContext.fetch(fetchRequest) //拋出異常
        } catch let error as NSError {
            print("無法讀取!\(error),\(error.userInfo)")
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func save(name:String) {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            return
        } //判斷appDelegate是否符合條件 符合的話就執(zhí)行下面的代碼 不符合直接return退出
        let manageContext = appDelegate.persistentContainer.viewContext
        let entity = NSEntityDescription.entity(forEntityName: "Person", in: manageContext)!
        let person = NSManagedObject(entity: entity, insertInto: manageContext)
        person.setValue(name, forKey: "name")
        
        do {
            try manageContext.save() //拋出異常
            people.append(person)
        } catch let error as NSError {
            print("無法保存!\(error),\(error.userInfo)")
        }
    }

}

//UITableViewDataSource
extension ViewController:UITableViewDataSource {
    func tableView(_ tableView:UITableView,numberOfRowsInSection section: Int) -> Int {
        return people.count
    }
    func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath) -> UITableViewCell {
        let person = people[indexPath.row]
        let cell = tabelView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = person.value(forKeyPath: "name") as? String
        return cell
    }
}

現(xiàn)在解釋一下涉及到CoreData的一些代碼:

var people:[NSManagedObject] = []

我們將people這個數(shù)組定義為NSManagedObject類型,NSManagedObject類代表存儲在CoreData中的一個單獨的對象,而且它很靈活,在你的數(shù)據(jù)模型中,它可以采取任何實體的形式。

cell.textLabel?.text = person.value(forKeyPath: "name") as? String

我們?nèi)绾螐膶嶓w中得到屬性呢?通過KVC
簡單說一下KVC,就是指在iOS開發(fā)中,可以允許開發(fā)者通過Key名直接訪問對象的屬性,或者給對象的屬性賦值。而不需要調(diào)用明確的存取方法。這樣就可以在運行時動態(tài)在訪問和修改對象的屬性。而不是在編譯時確定。具體關于KVC的知識還在探索中......(手動尷尬)

func save(name:String) {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            return
        } //判斷appDelegate是否符合條件 符合的話就執(zhí)行下面的代碼 不符合直接return退出
        let manageContext = appDelegate.persistentContainer.viewContext
        let entity = NSEntityDescription.entity(forEntityName: "Person", in: manageContext)!
        let person = NSManagedObject(entity: entity, insertInto: manageContext)
        person.setValue(name, forKey: "name")
        
        do {
            try manageContext.save() //拋出異常
            people.append(person)
        } catch let error as NSError {
            print("無法保存!\(error),\(error.userInfo)")
        }
    }

我們要通過CoreData來保存數(shù)據(jù),需要兩個步驟:
(1)將一個managed object添加到一個managed object context中;
(2)在managed object context中實行改變并保存。

override func viewWillAppear(_ animated: Bool) {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            return
        } //判斷appDelegate是否符合條件 符合的話就執(zhí)行下面的代碼 不符合直接return退出
        let manageContext = appDelegate.persistentContainer.viewContext
        let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Person")
        
        do {
            people = try manageContext.fetch(fetchRequest) //拋出異常
        } catch let error as NSError {
            print("無法讀取!\(error),\(error.userInfo)")
        }
    }

最后,保存到CoreData中的數(shù)據(jù)需要被取出才能顯示,需要注意的是:伴隨CoreData進行的任何操作都需要一個managed object context。

最后的結(jié)果:

屏幕快照 2016-10-23 下午9.56.43.png

在CoreData中,可以給實體定義很多屬性(廢話(⊙o⊙)…),不同的屬性對應不同的種類,有以下幾種:

屏幕快照 2016-10-23 下午8.27.36.png

常見的幾個就不多說了,說說兩個不常見的:Binary Data和Transformable

Binary Data顧名思義,二進制數(shù)據(jù),任何可序列化為0和1的屬性都可以使用這個種類,比如圖片,PDF等等,看似變得方便了,但是當你的二進制數(shù)據(jù)很龐大時它會影響到程序的表現(xiàn),試想一下每次訪問實體的時候都要加載大量的二進制數(shù)據(jù),甚至你可能只是想訪問實體的名稱......
還好CoreData提供了解決方法,就是當你選擇了二進制數(shù)據(jù)作為你屬性的種類時,你可以同時勾選Allows External Storage,如圖:


屏幕快照 2016-10-23 下午8.53.16.png

接下來說說Transformable
在CoreData中,我們可以選擇任何數(shù)據(jù)類型,甚至是我們自己定義的,我們只需要將類型選擇為Transformable并且遵循NSCoding協(xié)議即可。
NSCoding協(xié)議目前我還不是很清楚,在以后的學習中會加入到文章中來。

CoreData的學習才剛剛開始,一些概念還理解得并不是很透徹,在今后的學習中還要不斷完善自己。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容