注:本文来自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选项:
选择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。
从对象库拖一个Table View放在View Controller上使它覆盖整个view。
如果还没有覆盖,可以打开Interface Builder的文档框选择Table View,按住ctrol拖到他的父视图也就是View上,选择Leading Space to Container Margin约束。
再重复上面的操作三次,选择约束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 , 你的面板现在看起来应该如下图:
每次你点击右上角的Add,都要弹出一个包含文本框的弹出框。你可以在里面写上某某的姓名,弹出框消失的时候你要保存name刷新tableView。
在你做这些之前,你需要将viewController设为tableView的数据源,选择table View ,Ctrl-drag(按住ctrol拖动,以后都用Ctrl-drag)导航栏上面的黄色viewController图标,如下图所示,然后选择dataSource
为了不让你混淆,你不需要添加delegate,因为点击cell不需要任何行为。
打开Assistant Editor。Ctrl-drag tableView到ViewController.swift,去添加一个outlet的定义。
将新的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按钮,弹出框将会展示如图:
添加几条数据,你的界面将会展示如下图:
你的表视图将会展示数组的数据,但是我们少了持久化。数组的数据是存在内存的,如果你退出app,重启设备,再进app的时候list就被清空了。
Core Data提供了持久化,意味着他可以将数据更长久的存储,就算重新加载或者重启设备,数据依然存在。
你现在还没有添加任何Core Data , 所以当你退出你的app后他将不会存储任何东西。我们来测试下,点击home键 , 如果你使用的模拟器。按Shift+⌘+H 。回到home界面。
下面主要说下步骤
- 添加Entity(实体)
点击添加,默认名是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中 建议看原版