第一章:你的第一个Core Data App
注:本文来自Core Data by tutorials 2.0 , swift + iOS 9 .
本章你将会编写你第一个Core Data App,你将会发现Xcode提供的这些资源多么容易上手。
学完本章,你将会掌握以下知识:
- 使用Xcode的模型编辑器(model editor)将你想保存的数据模型(model data)保存到Core Data
- 向Core Data中新增记录
- 从Core Data中取回一组记录
- 将取回的结果用tableView展示出来
开始
打开Xcode创建一个Single View Controller , 给App起名为HitList确认勾选Use Core Data选项:
![](https://img.haomeiwen.com/i954071/887be158cb621cb6.png)
选择Use Core Data后使 Xcode 在AppDelegate 中产生被称为Core Data stack(Core Data 堆栈)的代码示例。
Core Data stack由一套促进从Core Data中存储和获取信息的对象组成,一个管理Core Data 全局状态,一个代表数据模型,还有一些其他的对象。
你将会在这章了解这些对象。稍后,你还要写你自己的Core Data stack。标准的stack可以很好的应用在很多app中,但是基于你的app和数据,你可以自定义stack使他更高效。
注意:不是所有的Xcode模板都有Core Data选项,在Xcode 7中,只有Master-Detail Application 和 Single View Application 模板有Use Core Data选项。
这个示例代码很简单。一个简单的tableview有一些names列表title为"hit list". 你可以给列表新增names,最后你将使用Core Data确认这些数据已经被持久的存储。你可以把他改成"Favorites list"或者其他你喜欢的。
点击Main.storyboard打开Interface Builder。下一步,嵌入一个navigation controller.在Xcode上选择Editor菜单,选择Embed In然后Navigation Controller。
![](https://img.haomeiwen.com/i954071/176fc20101275e27.png)
从对象库拖一个Table View放在View Controller上使它覆盖整个view。
如果还没有覆盖,可以打开Interface Builder的文档框选择Table View,按住ctrol拖到他的父视图也就是View上,选择Leading Space to Container Margin约束。
![](https://img.haomeiwen.com/i954071/d34ccac933dfa701.png)
再重复上面的操作三次,选择约束Trailing Space to Container Margin,** Vertical Spacing to Top Layout Guide和Vertical Spacing to Bottom Layout Guide**。如果你熟悉Auto Layout,你就会认识这些约束是用来约束table view的size跟他父视图size的关系。
下一步,拖一个Bar Button Item放在viewController的导航条上。双击item将文本改为Add , 你的面板现在看起来应该如下图:
![](https://img.haomeiwen.com/i954071/e701e049d9f7c504.png)
每次你点击右上角的Add,都要弹出一个包含文本框的弹出框。你可以在里面写上某某的姓名,弹出框消失的时候你要保存name刷新tableView。
在你做这些之前,你需要将viewController设为tableView的数据源,选择table View ,Ctrl-drag(按住ctrol拖动,以后都用Ctrl-drag)导航栏上面的黄色viewController图标,如下图所示,然后选择dataSource
![](https://img.haomeiwen.com/i954071/739457db4691d2f9.png)
为了不让你混淆,你不需要添加delegate,因为点击cell不需要任何行为。
打开Assistant Editor。Ctrl-drag tableView到ViewController.swift,去添加一个outlet的定义。
![](https://img.haomeiwen.com/i954071/10d6a654cf6a4a97.png)
将新的IBOutlet属性命名为tableView,下面是结果:
@IBOutlet weak var tableView: UITableView!
Ctrl-drag那个Add 按钮到ViewController.swift ,创建一个Action起名为addName:
@IBAction func addName(sender: AnyObject) {
}
在ViewController.swift添加一个属性
//Insert below the tableView IBOutlet
var names = [String]()
names是一个可变数组用来保存string数据供tableView展示
在viewDidLoad()中做如下改变:
override func viewDidLoad() {
super.viewDidLoad()
title = "\\"The List\\""
tableView.registerClass(UITableViewCell.self,forCellReuseIdentifier: "Cell")
}
上面的代码将会设置一个title,注册一个UITableViewCell类,为了复用。
viewController将实现UITableViewDataSource协议、
class ViewController: UIViewController, UITableViewDataSource {
Xcode这时候会报红,没有实现协议中必须实现的方法。实现下面的数据源方法:
// MARK: UITableViewDataSource
func tableView(tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
return names.count
}
func tableView(tableView: UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")
cell!.textLabel!.text = names[indexPath.row]
return cell!
}
如果你以前用过UITableView,这段代码应该很熟悉,第一个方法返回tableVIew将会有多少行,第二个方法使tableViewCell出列,然后数组对应的值赋给他的textLabel来显示
先别急着运行程序,首先,你需要一个添加names的方式,这样tableview才能展示他们。
实现addName方法:
//Implement the addName IBAction
@IBAction func addName(sender: AnyObject) {
let alert = UIAlertController(title: "New Name",message: "Add a new name",preferredStyle: .Alert)
let saveAction = UIAlertAction(title: "Save",style: .Default,handler:{(action:UIAlertAction) -> Void in
let textField = alert.textFields!.first
self.names.append(textField!.text!)
self.tableView.reloadData()
})
let cancelAction = UIAlertAction(title: "Cancel",style: .Default) { (action: UIAlertAction) -> Void in
}
alert.addTextFieldWithConfigurationHandler {(textField: UITextField) -> Void in
}
alert.addAction(saveAction)
alert.addAction(cancelAction)
presentViewController(alert,animated: true,completion: nil)
}
每次你点击Add按钮的时候,这个方法将会展示一个弹出框(UIAlertController),框上有两个按钮,Save和Cancel 。
这里save不管text是否正确,把它加入name数组,重新加载tableView。因为names是tableview的数据支持,你在textfield输入任何值,save后都会显示在tableview。
最后,是时候编译运行你的app了,点击Add按钮,弹出框将会展示如图:
![](https://img.haomeiwen.com/i954071/91949dcb304fa294.png)
添加几条数据,你的界面将会展示如下图:
![](https://img.haomeiwen.com/i954071/045f9461e180be49.png)
你的表视图将会展示数组的数据,但是我们少了持久化。数组的数据是存在内存的,如果你退出app,重启设备,再进app的时候list就被清空了。
Core Data提供了持久化,意味着他可以将数据更长久的存储,就算重新加载或者重启设备,数据依然存在。
你现在还没有添加任何Core Data , 所以当你退出你的app后他将不会存储任何东西。我们来测试下,点击home键 , 如果你使用的模拟器。按Shift+⌘+H 。回到home界面。
![](https://img.haomeiwen.com/i954071/9b9703c99956c86d.png)
下面主要说下步骤
- 添加Entity(实体)
![](https://img.haomeiwen.com/i954071/af393cee6461edb1.png)
点击添加,默认名是Entity,选中回车 改名位People
在Attribute那里添加一个属性
name
下面简单在代码中对name进行存取
- 存取
前面声明字符串数组的地方替换成
var people = [NSManagedObject]()
cell中显示的时候用kvc取值
// MARK: - tableView cell单元格信息
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
let person = people[indexPath.row]
cell.textLabel?.text = person.valueForKey("name") as? String
return cell
}
添加按钮 保存操作
//MARK: -添加元素
@IBAction func addItem(sender: AnyObject) {
let alert = UIAlertController(title: "新姓名", message: "添加新姓名", preferredStyle: .Alert)
let save = UIAlertAction(title: "保存", style: .Default) { (action) -> Void in
let textField = alert.textFields!.first
self.saveName(textField?.text) //这里保存到coredata
self.tableView.reloadData()
}
let cancel = UIAlertAction(title: "取消",
style: .Default) { (action: UIAlertAction) -> Void in
}
alert.addTextFieldWithConfigurationHandler {
(textField: UITextField) -> Void in
}
alert.addAction(cancel)
alert.addAction(save)
presentViewController(alert,
animated: true,
completion: nil)
}
//存储name
func saveName(value:String?){
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("People", inManagedObjectContext: managedContext)
let person = NSManagedObject(entity: entity!,insertIntoManagedObjectContext: managedContext)
person.setValue(value, forKey: "name")
do {
try managedContext.save()
//5
people.append(person)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
第二次进页面的时候 去取值
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "People")
do {
let results =
try managedContext.executeFetchRequest(fetchRequest)
people = results as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
代码不是很难理解 这些属性 都加在appdelegate中 建议看原版