iOS开发笔记之Core Data(一)

CoreData 是 iOS3.0 时引入的一个数据持久化的框架。利用这个框架我们可以非常方便的对数据进行操作。
可以先从一个简单的例子来看一下CoreData到底能干啥:

首先我们要新建一个单页面项目,勾选选项CoreData;

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

然后在storyboard中拖一个tableView到ViewController上,并导入一个NavigationController,在导航栏上添加一个button(此处不是CoreData的重点所以我们简单叙述),同时与代码建立关联;

屏幕快照 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

现在开始实现功能,功能很简单就是点击添加按钮添加一个name到表格中,数据在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是否符合条件 符合的话就执行下面的代码 不符合直接return退出
        let manageContext = appDelegate.persistentContainer.viewContext
        let fetchRequest = NSFetchRequest(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是否符合条件 符合的话就执行下面的代码 不符合直接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
    }
}

现在解释一下涉及到CoreData的一些代码:

var people:[NSManagedObject] = []

我们将people这个数组定义为NSManagedObject类型,NSManagedObject类代表存储在CoreData中的一个单独的对象,而且它很灵活,在你的数据模型中,它可以采取任何实体的形式。

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

我们如何从实体中得到属性呢?通过KVC
简单说一下KVC,就是指在iOS开发中,可以允许开发者通过Key名直接访问对象的属性,或者给对象的属性赋值。而不需要调用明确的存取方法。这样就可以在运行时动态在访问和修改对象的属性。而不是在编译时确定。具体关于KVC的知识还在探索中......(手动尴尬)

func save(name:String) {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            return
        } //判断appDelegate是否符合条件 符合的话就执行下面的代码 不符合直接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来保存数据,需要两个步骤:
(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是否符合条件 符合的话就执行下面的代码 不符合直接return退出
        let manageContext = appDelegate.persistentContainer.viewContext
        let fetchRequest = NSFetchRequest(entityName: "Person")
        
        do {
            people = try manageContext.fetch(fetchRequest) //抛出异常
        } catch let error as NSError {
            print("无法读取!\(error),\(error.userInfo)")
        }
    }

最后,保存到CoreData中的数据需要被取出才能显示,需要注意的是:伴随CoreData进行的任何操作都需要一个managed object context。

最后的结果:

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

在CoreData中,可以给实体定义很多属性(废话(⊙o⊙)…),不同的属性对应不同的种类,有以下几种:

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

常见的几个就不多说了,说说两个不常见的:Binary Data和Transformable

Binary Data顾名思义,二进制数据,任何可序列化为0和1的属性都可以使用这个种类,比如图片,PDF等等,看似变得方便了,但是当你的二进制数据很庞大时它会影响到程序的表现,试想一下每次访问实体的时候都要加载大量的二进制数据,甚至你可能只是想访问实体的名称......
还好CoreData提供了解决方法,就是当你选择了二进制数据作为你属性的种类时,你可以同时勾选Allows External Storage,如图:


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

接下来说说Transformable
在CoreData中,我们可以选择任何数据类型,甚至是我们自己定义的,我们只需要将类型选择为Transformable并且遵循NSCoding协议即可。
NSCoding协议目前我还不是很清楚,在以后的学习中会加入到文章中来。

CoreData的学习才刚刚开始,一些概念还理解得并不是很透彻,在今后的学习中还要不断完善自己。

你可能感兴趣的:(iOS开发笔记之Core Data(一))