当前位置:网站首页>Swift简单实现待办事项
Swift简单实现待办事项
2022-07-25 09:21:00 【yueliangmua】
待办事项的创建无非就是实现增删改查,可以根据TableView自带的editing来实现更改顺序和滑动删除,创建button的点击事件来更改是否打勾的状态,通过正反向传值、设置代理来实现更改label内容和添加待办事项。
目录
最终效果图




视频效果
待办事项效果图
创建TableView
待办事项的设计通常使用tableVIew会让页面更加友好操作方便,我通常在mainstory里搭建所需页面。如下图所示。

先拉一个UITableView进来,再给里面拉一个TableViewCell进行操作。接着就是在cell里面添加构成元素了,根据图片很容易可以发现共含两个元素,一个就是可供点击的button,另一个就是展示内容的label,于是我们先添加一个占位符。
常量constant代码
import Foundation
import UIKit
let kTodoTableVCID = "TodoTableVCID"
let kTodoCellID = "TodoCellID"
let kAddTodoID = "AddTodoID"
let kEditTodoID = "EditTodoID"
func pointIcon(_ iconName: String, _ pointSize: CGFloat = 22) -> UIImage?{
let config = UIImage.SymbolConfiguration(pointSize: pointSize)
return UIImage(systemName: iconName, withConfiguration: config)
}
连接mainstory和代码
将刚刚所设计的UI连接上TodosTableView的swift文件。根据MVC模式,单独创建一个swift文件储存模版元素。
import Foundation
//class Todo{
// var name = ""
// var checked = ""
//}
struct Todo {
var name: String
var checked: Bool
}
在TodosTableVC.swift文件中用数组存储cell中的初始内容。
var todos = [
Todo(name: "旅游", checked: false),
Todo(name: "复习", checked: false),
Todo(name: "图书馆", checked: false),
Todo(name: "面试", checked: false),
Todo(name: "入职", checked: false)
]
//row用于后续使用
var row = 0将TableView放入navigation中,实现界面的出栈入栈
设置NavigationItem的内容,用UIControllerView自带的edititem实现编辑按钮。
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.
editButtonItem.title = nil
editButtonItem.image = pointIcon("arrow.up.arrow.down.circle.fill")
navigationItem.leftBarButtonItem = editButtonItem
navigationItem.rightBarButtonItem?.image = pointIcon("plus.circle.fill", 22)
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
if isEditing{
editButtonItem.image = nil
editButtonItem.title = "完成"
}else{
editButtonItem.title = nil
editButtonItem.image = pointIcon("arrow.up.arrow.down.circle.fill")
}
}在prepar方法中设置页面跳转时的参数传递
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == kAddTodoID{
let vc = segue.destination as! TodoTableVC
vc.delegate = self
}else if segue.identifier == kEditTodoID{
let vc = segue.destination as! TodoTableVC
vc.delegate = self
let cell = sender as! TodoCell
//cell-->indexpath
//tableView.indexPath(for: cell)
//indexpath-->cell
//tableView.cellForRow(at: indexPath) as! TodoCell
row = tableView.indexPath(for: cell)!.row
vc.name = todos[row].name
}
}设置TodosTableVC的delegate
设置点击时的背景颜色只显示瞬间的灰色,在选中时就设置取消选中。
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
// let vc = storyboard?.instantiateViewController(withIdentifier: kTodoTableVCID) as! TodoTableVC//在storyboar上找制作好的vc
// navigationController?.pushViewController(vc, animated: true)
}设置编辑模式,在isEditing状态可以排序但取消删除并且取消锁进,非isEditing状态可以进行滑动删除。
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
if !isEditing{
return .delete
}else{
return .none
}
}
override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}TodoTableVCDelegate用于反向传值,实现新增待办事项和修改已有待办事项
extension TodosTableVC: TodoTableVCDelegate{
func didAdd(name: String) {
todos.append(Todo(name: name, checked: false))
tableView.insertRows(at: [IndexPath(row: todos.count - 1, section: 0)], with: .automatic)
// tableView.reloadData()
}
func didEdit(name: String) {
todos[row].name = name
let indexPath = IndexPath(row: 0, section: 0)
let cell = tableView.cellForRow(at: indexPath) as! TodoCell
cell.todoLabel.text = name
tableView.reloadData()
}
}
完整代码如下
import UIKit
extension TodosTableVC{
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
// let vc = storyboard?.instantiateViewController(withIdentifier: kTodoTableVCID) as! TodoTableVC//在storyboar上找制作好的vc
// navigationController?.pushViewController(vc, animated: true)
}
// override func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
// return "点击以删除"
// }
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
if !isEditing{
return .delete
}else{
return .none
}
}
override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
}
extension TodosTableVC: TodoTableVCDelegate{
func didAdd(name: String) {
todos.append(Todo(name: name, checked: false))
tableView.insertRows(at: [IndexPath(row: todos.count - 1, section: 0)], with: .automatic)
// tableView.reloadData()
}
func didEdit(name: String) {
todos[row].name = name
let indexPath = IndexPath(row: 0, section: 0)
let cell = tableView.cellForRow(at: indexPath) as! TodoCell
cell.todoLabel.text = name
tableView.reloadData()
}
}
设置TodosTableVC的dataSource
默认返回一个section和todos数据个cell
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return todos.count
}cell的复用方法中设置选中时图标的变化和字体颜色
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: kTodoCellID, for: indexPath) as! TodoCell
let checkBoxBtn = cell.checkBoxBtn!
let todoLabel = cell.todoLabel!
let initSelected = todos[indexPath.row].checked
// var contentConfiguration = cell.defaultContentConfiguration()
// contentConfiguration.text = "昵称"
// contentConfiguration.secondaryText = "个性签名"
// contentConfiguration.image = UIImage(systemName: "star")
// cell.contentConfiguration = contentConfiguration
// Configure the cell...
checkBoxBtn.isSelected = initSelected
todoLabel.text = todos[indexPath.row].name
todoLabel.textColor = initSelected ? .tertiaryLabel : .label
//改
// checkBoxBtn.addAction(UIAction(handler: { action in
// self.todos[indexPath.row].checked.toggle()
// let checked = self.todos[indexPath.row].checked
// checkBoxBtn.isSelected = checked
// todoLabel.textColor = checked ? .tertiaryLabel : .label
// }), for: .touchUpInside)
checkBoxBtn.tag = indexPath.row
checkBoxBtn.addTarget(self, action: #selector(toggleCheck), for: .touchUpInside)
return cell
}
@objc func toggleCheck(checkBoxBtn: UIButton){
// 改
let row = checkBoxBtn.tag
self.todos[row].checked.toggle()
let checked = self.todos[row].checked
checkBoxBtn.isSelected = checked
let cell = tableView.cellForRow(at: IndexPath(row: row, section: 0)) as! TodoCell
cell.todoLabel.textColor = checked ? .tertiaryLabel : .label
}设置移动时的数据变化
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
let todoToRemove = todos[fromIndexPath.row]
todos.remove(at: fromIndexPath.row)
todos.insert(todoToRemove, at: to.row)
tableView.reloadData()
}完整代码如下
import UIKit
extension TodosTableVC{
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: kTodoCellID, for: indexPath) as! TodoCell
let checkBoxBtn = cell.checkBoxBtn!
let todoLabel = cell.todoLabel!
let initSelected = todos[indexPath.row].checked
// var contentConfiguration = cell.defaultContentConfiguration()
// contentConfiguration.text = "昵称"
// contentConfiguration.secondaryText = "个性签名"
// contentConfiguration.image = UIImage(systemName: "star")
// cell.contentConfiguration = contentConfiguration
// Configure the cell...
checkBoxBtn.isSelected = initSelected
todoLabel.text = todos[indexPath.row].name
todoLabel.textColor = initSelected ? .tertiaryLabel : .label
//改
// checkBoxBtn.addAction(UIAction(handler: { action in
// self.todos[indexPath.row].checked.toggle()
// let checked = self.todos[indexPath.row].checked
// checkBoxBtn.isSelected = checked
// todoLabel.textColor = checked ? .tertiaryLabel : .label
// }), for: .touchUpInside)
checkBoxBtn.tag = indexPath.row
checkBoxBtn.addTarget(self, action: #selector(toggleCheck), for: .touchUpInside)
return cell
}
@objc func toggleCheck(checkBoxBtn: UIButton){
// 改
let row = checkBoxBtn.tag
self.todos[row].checked.toggle()
let checked = self.todos[row].checked
checkBoxBtn.isSelected = checked
let cell = tableView.cellForRow(at: IndexPath(row: row, section: 0)) as! TodoCell
cell.todoLabel.textColor = checked ? .tertiaryLabel : .label
}
// 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)
tableView.reloadData()
} 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, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
let todoToRemove = todos[fromIndexPath.row]
todos.remove(at: fromIndexPath.row)
todos.insert(todoToRemove, at: to.row)
tableView.reloadData()
}
}
TodoCell的设置
import UIKit
class TodoCell: UITableViewCell {
@IBOutlet weak var todoLabel: UILabel!
@IBOutlet weak var checkBoxBtn: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
checkBoxBtn.setImage(UIImage(systemName: "checkmark.circle.fill"), for: .selected)
checkBoxBtn.setImage(UIImage(systemName: "circle"), for: .normal)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
cell中含todoLabel和checkBoxBtn,设置checkBoxBtn选中和未选中时的图标,setSelected设置选中标签时的背景。
创建第二个TableView,TodoTableView
搭建页面连接代码
设置didAdd和didEdit的协议
protocol TodoTableVCDelegate{
func didAdd(name: String)
func didEdit(name: String)
}通过textView输入框内容是否为空判断是增还是改
@IBAction func done(_ sender: Any) {
navigationController?.popViewController(animated: true)
if !todoTextView.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty{
if name != nil{
delegate?.didEdit(name: todoTextView.text)
}else{
delegate?.didAdd(name: todoTextView.text)
}
}
}点击返回按钮和完成按钮页面出栈
@IBAction func back(_ sender: Any) {
navigationController?.popViewController(animated: true)
}设置顶部返回和完成图标
override func viewDidLoad() {
super.viewDidLoad()
todoTextView.becomeFirstResponder()
todoTextView.delegate = self
todoTextView.text = name
if name != nil{
navigationItem.title = "编辑待办事项"
}
navigationItem.leftBarButtonItem?.image = pointIcon("chevron.backward.circle.fill")
navigationItem.rightBarButtonItem?.image = pointIcon("checkmark.circle.fill")
}设置textview的实时换行,遵循textViewdelegat协议,实现实时检测换行方法
extension TodoTableVC: UITextViewDelegate{
func textViewDidChange(_ textView: UITextView) {
// tableView.beginUpdates()
// tableView.endUpdates()
tableView.performBatchUpdates { }
}
}布局刷新。
边栏推荐
- 换电脑后如何配置SSH
- 梦想启航(第一篇博客)
- MySQL的索引、视图与事务
- How to write Android switching interface with kotlin
- sqli-labs Basic Challenges Less11-22
- *7-2 CCF 2015-09-2 日期计算
- 基本的网络知识
- The jar package has been launched on Alibaba cloud server and the security group has been opened, but postman still can't run. What should we do
- Flex 布局语法与用例
- Week summary
猜你喜欢
随机推荐
粗柳簸箕细柳斗,谁嫌爬虫男人丑 之 异步协程半秒扒光一本小说
最短路问题 Bellman-Ford(单源最短路径)(图解)
Week小结
*6-1 CCF 2015-03-2 数字排序
梦想启航(第一篇博客)
< T> Generic method demonstration
App的生命周期和AppleDelegate,SceneDelegate
@4-1 CCF 2020-06-1 线性分类器
[De1CTF 2019]SSRF Me
@3-1 CCF 2020-09-1 称检测点查询
Go基础1
Why use json.stringify() and json.parse()
链表--基本操作
OC--对象复制
C language and SQL Server database technology
Flex 布局语法与用例
Go foundation 4
OC--Foundation--集合
sqli-labs Basic Challenges Less11-22
cf #785(div2) C. Palindrome Basis








