以tableView为基础来完成一个任务清单程序。
需求分析:
1.写入任务。
2.删除任务。
3.编辑现有任务。
软件的基础是tableViewController,其中主页面是一个计划列表,可以完成删除操作,点击进入副页面,可以完成写入和编辑操作。
创建Xcode项目后在sb中加入一个tableView,将初始化箭头拉到tableView上,删除自带的view以及ViewController。
项目文件:
View中有sb和初始化界面。
Controller需要有一个控制主页面的TasksController,用来控制主页面,也是显示任务清单的页面。对副页面以TaskController来控制,主要针对单个任务的修改和加入。还需要一个CellController来控制主页面中任务栏中字符的显示。
Model中只需要制定要写下的计划名称,以及一个是否完成的标记。
在sb中加入Navigation Controller做页面切换
在taskModel中写下
struct TaskModel:Codable {
//Codable为了使得Task可以被转码记录与手机上
var name = "" //任务名称
var mark = false //是否完成的标记
}
主页面与TasksController相连,全局遍变量中定义一个row,指向用户所选定的cell。
以及一个数组tasks[ ]为TaskModel的实例来记录任务的name还有是否完成的Bool值变量mark。
var row = 0 //指向用户选定的行数
var tasks:[TaskModel] = [] //实例化Model
于CellController中连接label
@IBOutlet weak var mark: UILabel! //标记√
@IBOutlet weak var task: UILabel! //任务名字
定义一个cell为CellController的实例,从而可以改变其中label的值
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "task", for: indexPath) as! CellController
cell.task.text = tasks[indexPath.row].name
cell.mark.text = tasks[indexPath.row].mark ? "√" : ""
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if !isEditing{
tasks[indexPath.row].mark = !task[indexPath.row].mark //当用户点击cell之后,将mark取反
saveData()//存储数据
let cell = tableView.cellForRow(at: indexPath) as! TaskCell
cell.mark.text = todos[indexPath.row].mark ? "√" : ""
tableView.deselectRow(at: indexPath, animated: true)
}
}
副页面写入任务后需要反向传值给主页面
在副页面加入Text Field,与副页面的Controller连接
需要将taskInput的值传入主页面
在副页面中写
protocol TodoDelegat {//1.定义协议
func didAdd(name:String)
func didEdit(name:String)
}
var delegate:TaskDelegate? //2.定义属性
@IBAction func done(_ sender: Any) { //3.在需要传值的地方引入Delegate
if let name = taskInput.text,!name.isEmpty{
if self.name != nil{
delegate?.didEdit(name: name)
}else{
delegate?.didAdd(name: name)
}
}
navigationController?.popViewController(animated: true)//输入完成后副页面出栈,显示主页面
}
在主页面中
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addTask"{
let vc = segue.destination as! TaskController
vc.delegate = self
}else if segue.identifier == "editTask"{
let vc = segue.destination as! TaskController
let cell = sender as! TaskCell
row = tableView.indexPath(for: cell)!.row
vc.name = tasks[row].name
vc.delegate = self //3.表面delegete的委托者,形成闭环
}
}
extension TasksController:TaskDelegat{//1.遵守协议
func didAdd(name: String) {//2.实现方法
tasks.append(Task(name: name, mark: false))
saveData()
let indexPath = IndexPath(row: tasks.count - 1, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
}
func didEdit(name: String) {//2.实现方法
tasks[row].name = name
saveData()
let indexPath = IndexPath(row: row, section: 0)
let cell = tableView.cellForRow(at: indexPath) as! TaskCell
cell.task.text = name
}
func saveData(){
do{
let data = try JSONEncoder().encode(todos)
UserDefaults.standard.set(data,forKey: "tasks")
}catch{
print(error)
}
}
}