当前位置:网站首页>Swift简单实现待办事项

Swift简单实现待办事项

2022-07-25 09:21:00 yueliangmua

待办事项的创建无非就是实现增删改查,可以根据TableView自带的editing来实现更改顺序和滑动删除,创建button的点击事件来更改是否打勾的状态,通过正反向传值、设置代理来实现更改label内容和添加待办事项。

目录

最终效果图

视频效果

 创建TableView

连接mainstory和代码

 将TableView放入navigation中,实现界面的出栈入栈

 设置TodosTableVC的delegate

设置TodosTableVC的dataSource 

 TodoCell的设置

创建第二个TableView,TodoTableView


最终效果图

视频效果

待办事项效果图

 创建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 { }
    }
}

布局刷新。

原网站

版权声明
本文为[yueliangmua]所创,转载请带上原文链接,感谢
https://blog.csdn.net/yueliangmua/article/details/125735173