Todos的功能:
添加数据
更改数据
删除数据
批量删除数据
移动数据
Main.storyboard:
删除原本的ViewController 创建一个Table View Controller,并且钩上Is Initial View Controller
删除左栏的ViewController,在Cocoa Touch Class添加一个TableViewController,命名为TodosController并整理为MVC格式
Model内创建Todo结构体
import Foundation
struct Todo {
var name = ""
var checked = false
}
实例化Todo
class TableViewController: UITableViewController {
var todos = [
Todo(name: "吃大象", checked: false),
Todo(name: "开飞机", checked: false),
Todo(name: "造坦克", checked: false),
Todo(name: "坐火箭", checked: false),
Todo(name: "炸学校", checked: false)
]
设置tableview的段数和行数
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return todos.count
}
创建TableViewCell
在cell里面增加两个label
与cell连接
@IBOutlet weak var checkMark: UILabel!
@IBOutlet weak var Todo: UILabel!
更改cell的Accessory属性
将todos里面的Todo依次放入cell中:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "todo", for: indexPath) as! TodoCell
cell.checkMark.text = todos[indexPath.row].checked ? "√" : ""
cell.todo.text = todos[indexPath.row].name
// Configure the cell...
return cell
}
效果:
添加点击后打勾与取消打勾效果
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//更改数据
todos[indexPath.row].checked = !todos[indexPath.row].checked
//更新视图
let cell = tableView.cellForRow(at: indexPath) as! TodoCell
cell.checkMark.text = todos[indexPath.row].checked ? "√" : ""
tableView.deselectRow(at: indexPath, animated: true)
}
实现添加功能
创建TodoController,添加一个text
用Navigation Controller连接,并添加一个bar button item,与新的controller连接
设置新的tableview controller的行数列数
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 1
}
用protocol实现反向传值
protocol TodoDelegate {
func didAdd(name: String)
}
class TodoController: UITableViewController {
var delegate :TodoDelegate?
按完成时调用didAdd函数,并且弹出界面
@IBAction func done(_ sender: UIBarButtonItem) {
if let name = todoInput.text,!name.isEmpty {
delegate?.didAdd(name: name)
}
navigationController?.popViewController(animated: true)
}
TodosController里面实现TodoDelegate的didAdd函数
extension TodosController:TodoDelegate {
func didAdd(name: String) {
//添加数据
todos.append(Todo(name: name, checked: false))
//更改视图
let indexPath = IndexPath.init(row: todos.count - 1, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
}
}
实现跳转
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addTodo" {
let vc = segue.destination as! TodoController
vc.delegate = self
}
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
效果:
实现编辑的功能
增加编辑函数
protocol TodoDelegate {
func didAdd(name: String)
func didEdit(name: String)
}
添加变量保留需要编辑的cell的内容
var name : String?
当name为空时调用编辑函数
@IBAction func done(_ sender: UIBarButtonItem) {
if let name = todoInput.text,!name.isEmpty {
if self.name != nil {
delegate?.didEdit(name: name)
}else{
delegate?.didAdd(name: name)
}
}
navigationController?.popViewController(animated: true)
}
每次页面出现当name不为空时让navigation的title变为编辑任务
override func viewDidLoad() {
super.viewDidLoad()
todoInput.becomeFirstResponder()
todoInput.text = name
if name != nil {
navigationController?.title = "编辑任务"
}
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
实现跳转
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addTodo" {
let vc = segue.destination as! TodoController
vc.delegate = self
}else if segue.identifier == "editTodo" {
let vc = segue.destination as! TodoController
let cell = sender as! TodoCell
let row = tableView.indexPath(for: cell)!.row
vc.name = todos[row].name
vc.delegate = self
}
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
实现编辑函数
func didEdit(name: String) {
todos[row].name = name
let indexPath = IndexPath(row: row, section: 0)
let cell = tableView.cellForRow(at: indexPath) as! TodoCell
cell.todo.text = name
}
实现效果:
实现删除数据
实现删除
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
//删除数据
todos.remove(at: indexPath.row)
//更新视图
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
将Delete改名为删除
override func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
return "删除"
}
效果:
实现批量删除
添加选中的按钮
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
navigationItem.leftBarButtonItem = self.editButtonItem
editButtonItem.title = "编辑"
}
更改选中的名字为中文
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
editButtonItem.title = isEditing ? "完成" : "编辑"
}
添加删除按钮
实现删除按钮的功能
@IBAction func batchDelegate(_ sender: UIBarButtonItem) {
if let indexPaths = tableView.indexPathsForSelectedRows {
for indexPath in indexPaths {
todos.remove(at: indexPath.row)
}
tableView.beginUpdates()
tableView.deleteRows(at: indexPaths, with: .automatic)
tableView.endUpdates()
}
}
实现效果
实现移动数据
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
let todo = todos[fromIndexPath.row]
todos.remove(at: fromIndexPath.row)
todos.insert(todo, at: to.row)
tableView.reloadData()
}
最后完成代码:
TodosController:
import UIKit
class TodosController: UITableViewController {
var row = 0
var todos = [
Todo(name: "吃大象", checked: false),
Todo(name: "开飞机", checked: false),
Todo(name: "造坦克", checked: false),
Todo(name: "坐火箭", checked: false),
Todo(name: "炸学校", checked: false)
]
@IBAction func batchDelegate(_ sender: UIBarButtonItem) {
if let indexPaths = tableView.indexPathsForSelectedRows {
for indexPath in indexPaths {
todos.remove(at: indexPath.row)
}
tableView.beginUpdates()
tableView.deleteRows(at: indexPaths, with: .automatic)
tableView.endUpdates()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
navigationItem.leftBarButtonItem = self.editButtonItem
editButtonItem.title = "编辑"
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
editButtonItem.title = isEditing ? "完成" : "编辑"
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return todos.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "todo", for: indexPath) as! TodoCell
cell.checkMark.text = todos[indexPath.row].checked ? "√" : ""
cell.todo.text = todos[indexPath.row].name
// Configure the cell...
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if !isEditing {
//更改数据
todos[indexPath.row].checked = !todos[indexPath.row].checked
//更新视图
let cell = tableView.cellForRow(at: indexPath) as! TodoCell
cell.checkMark.text = todos[indexPath.row].checked ? "√" : ""
tableView.deselectRow(at: indexPath, animated: true)
}
}
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
//删除数据
todos.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
override func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
return "删除"
}
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
let todo = todos[fromIndexPath.row]
todos.remove(at: fromIndexPath.row)
todos.insert(todo, at: to.row)
tableView.reloadData()
}
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addTodo" {
let vc = segue.destination as! TodoController
vc.delegate = self
}else if segue.identifier == "editTodo" {
let vc = segue.destination as! TodoController
let cell = sender as! TodoCell
let row = tableView.indexPath(for: cell)!.row
vc.name = todos[row].name
vc.delegate = self
}
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
}
extension TodosController:TodoDelegate {
func didAdd(name: String) {
//添加数据
todos.append(Todo(name: name, checked: false))
//更改视图
let indexPath = IndexPath.init(row: todos.count - 1, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
}
func didEdit(name: String) {
//添加数据
todos[row].name = name
//更改视图
let indexPath = IndexPath(row: row, section: 0)
let cell = tableView.cellForRow(at: indexPath) as! TodoCell
cell.todo.text = name
}
}
TodoCell:
import UIKit
class TodoCell: UITableViewCell {
@IBOutlet weak var checkMark: UILabel!
@IBOutlet weak var todo: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
TodoController:
import UIKit
protocol TodoDelegate {
func didAdd(name: String)
func didEdit(name: String)
}
class TodoController: UITableViewController {
var delegate :TodoDelegate?
var name : String?
@IBOutlet weak var todoInput: UITextField!
@IBAction func done(_ sender: UIBarButtonItem) {
if let name = todoInput.text,!name.isEmpty {
if self.name != nil {
delegate?.didEdit(name: name)
}else{
delegate?.didAdd(name: name)
}
}
navigationController?.popViewController(animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
todoInput.becomeFirstResponder()
todoInput.text = name
if name != nil {
navigationController?.title = "编辑任务"
}
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 1
}
/*
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
// Configure the cell...
return cell
}
*/
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
Main.storyboard上的视图: