iOS开发Swift-13-界面跳转,新增待办事项,实时刷新,反向传值-待办事项App(2)

发布时间 2023-09-11 17:40:51作者: 临易

1.制作新增界面UI

进入Main界面,选中当前页面,点击右下角,选择Navigation Controller.Navigation Controller是一个容器,用于控制页面跳转.

 新建一个Table View Controller,作为跳转之后的页面.

 选中Table View,将他的Content改为Static Cells.

 选中Table View Section,将Rows改为1.

 将Table View的Style改为Inset Grouped.

 选中首页的Navigation Otem,将Title改为待办事项.

2.制作主界面新增按钮

要在Navigetion Item中新增按钮,需要使用Bar Button Item.拉到待办事项的右侧,作为新增待办事项的加号➕.

 将Item的Tint和Image改成相应的样式.

 3.跳转

将加号按钮Ctrl加拖拽到右边的Table View Controller页面.

 拖拽并选择后呈现效果如下.

 4.将"待办事项"修改为大标题.

选中Navigation Controller的Navigation Bar,勾选Prefers Large Titles.启动运行即可发现,"待办事项已经成为了大标题.

 5.将新增页面上的"<待办事项"这个返回按钮修改成一个返回图标.

新增一个Bar Butten Item,拖拽覆盖掉"<待办事项".在界面右上角也添加一个Bar Butten Item作为完成图标.

 将返回键的图标修改成对应样式.

 为完成键添加对应样式.

 6.新增一个CocoaTouch Class类型的class,类型选择为UITableViewController,取名为TodoTableViewController.

 在新增页中连接Class:TodoTableViewController.

 创建返回按钮的IBAction:back.

 创建完成按钮的IBAction:done.

 为back和done编写代码使点击他们能够返回首页.

TodoTableViewController:

import UIKit

class TodoTableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

      
    }

    @IBAction func back(_ sender: Any) {
        navigationController?.popViewController(animated: true)
    }
    
    @IBAction func done(_ sender: Any) {
        navigationController?.popViewController(animated: true)
    }
    
}

 7.将新增图标,返回图标,完成图标变大.

Constants:

import Foundation
import UIKit

let kTodoCellID = "TodoCellID"

//将图标变大的方法
func pointIcon(_ iconName: String, _ pointSize: CGFloat = 22) -> UIImage{
    let config = UIImage.SymbolConfiguration(pointSize: pointSize)
    return UIImage(systemName:iconName, withConfiguration: config)!
}

TodosViewController:

import UIKit

class TodosViewController: UITableViewController {
    
    var todos = [
        Todo(name: "学习iOS课程的基础课", checked: false),
        Todo(name: "学习iOS课程的零基础赏月App开发", checked: true),
        Todo(name: "学习iOS课程的零基础木琴App开发", checked: false),
        Todo(name: "学习iOS课程的零基础和风天气App开发", checked: false),
        Todo(name: "学习iOS课程的零基础待办事项App开发", checked: false),
        Todo(name: "学习iOS课程的小红书App开发", checked: false)
    ]

    override func viewDidLoad() {
        super.viewDidLoad()
        
        navigationItem.rightBarButtonItem?.image = pointIcon("plus.circle.fill")

        // 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
    //配置TableView的一些数据

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1   //总共有1个分类
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return todos.count   //总共有10个待办事项
    }

    
    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.todoLable!
        let initSelected = todos[indexPath.row].checked

//        // Configure the cell...
//        //配置主标题的文本
//        var contentConfiguration = cell.defaultContentConfiguration()
//        contentConfiguration.text = "昵称"   //主标题
//        contentConfiguration.secondaryText = "个性签名"    //副标题
//        contentConfiguration.image = UIImage(systemName: "star")  //图片
//        cell.contentConfiguration = contentConfiguration

        
        checkBoxBtn.isSelected = initSelected  //将cell的是否被选中属性改为todos的当前行的checked属性
        todoLabel.text = todos[indexPath.row].name
        todoLabel.textColor = initSelected ? .tertiaryLabel : .label   //三元运算符.根据是否被选中进行判断,如果被选中的话变成浅色,未被选中就是原来的Lable Color.
        
        cell.checkBoxBtn.addAction(UIAction(handler: { action in
            self.todos[indexPath.row].checked.toggle()    //如果check原来是true,被点击之后就进行取反,变成false.
            let checked = self.todos[indexPath.row].checked
            checkBoxBtn.isSelected = checked
            todoLabel.textColor = checked ? .tertiaryLabel : .label
            
        }), for: .touchUpInside)
        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 func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {

    }
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: 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.
    }
    

}

TodoTableViewController:

import UIKit

class TodoTableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.leftBarButtonItem?.image = pointIcon("chevron.left.circle.fill")
        navigationItem.rightBarButtonItem?.image = pointIcon("checkmark.circle.fill")
      
    }

    @IBAction func back(_ sender: Any) {
        navigationController?.popViewController(animated: true)
    }
    
    @IBAction func done(_ sender: Any) {
        navigationController?.popViewController(animated: true)
    }
    
}

8.使新增框可以输入多行文本

将多行文本控件text view拖入Table view中.

 修改Text View中Text的文本,将可滚动Scrolling Enable以及上面的上下滚动和左右滚动取消勾选.

 设置TextView的上下左右约束.

 将TextView作为Outlet拖拽到TodoTableViewController中.

 9.将输入的Text反向传值到首页.

指定identifier为AddTodoID.

 Constants:

import Foundation
import UIKit

let kTodoCellID = "TodoCellID"
let kAddTodoID = "AddTodoID"

//将图标变大的方法
func pointIcon(_ iconName: String, _ pointSize: CGFloat = 22) -> UIImage{
    let config = UIImage.SymbolConfiguration(pointSize: pointSize)
    return UIImage(systemName:iconName, withConfiguration: config)!
}

TodosViewController:

import UIKit

class TodosViewController: UITableViewController {
    
    
    var todos = [
        Todo(name: "学习iOS课程的基础课", checked: false),
        Todo(name: "学习iOS课程的零基础赏月App开发", checked: true),
        Todo(name: "学习iOS课程的零基础木琴App开发", checked: false),
        Todo(name: "学习iOS课程的零基础和风天气App开发", checked: false),
        Todo(name: "学习iOS课程的零基础待办事项App开发", checked: false),
        Todo(name: "学习iOS课程的小红书App开发", checked: false)
    ]

    override func viewDidLoad() {
        super.viewDidLoad()
        
        navigationItem.rightBarButtonItem?.image = pointIcon("plus.circle.fill")

        // 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
    //配置TableView的一些数据

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1   //总共有1个分类
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return todos.count   //总共有10个待办事项
    }

    
    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.todoLable!
        let initSelected = todos[indexPath.row].checked

//        // Configure the cell...
//        //配置主标题的文本
//        var contentConfiguration = cell.defaultContentConfiguration()
//        contentConfiguration.text = "昵称"   //主标题
//        contentConfiguration.secondaryText = "个性签名"    //副标题
//        contentConfiguration.image = UIImage(systemName: "star")  //图片
//        cell.contentConfiguration = contentConfiguration

        
        checkBoxBtn.isSelected = initSelected  //将cell的是否被选中属性改为todos的当前行的checked属性
        todoLabel.text = todos[indexPath.row].name
        todoLabel.textColor = initSelected ? .tertiaryLabel : .label   //三元运算符.根据是否被选中进行判断,如果被选中的话变成浅色,未被选中就是原来的Lable Color.
        
        cell.checkBoxBtn.addAction(UIAction(handler: { action in
            self.todos[indexPath.row].checked.toggle()    //如果check原来是true,被点击之后就进行取反,变成false.
            let checked = self.todos[indexPath.row].checked
            checkBoxBtn.isSelected = checked
            todoLabel.textColor = checked ? .tertiaryLabel : .label
            
        }), for: .touchUpInside)
        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 func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {

    }
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: 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?) {
        if segue.identifier == kAddTodoID{
            let vc = segue.destination as! TodoTableViewController
            vc.delegate = self
        }
    }
    

}

extension TodosViewController: TodoTableViewControllerDelegate{
    func didAdd(name: String){
        print(name)
    }
}

TodoTableViewController:

import UIKit

protocol TodoTableViewControllerDelegate{
    func didAdd(name: String)
}

class TodoTableViewController: UITableViewController {
    
    var delegate: TodoTableViewControllerDelegate?
    
    @IBOutlet weak var todoTextView: UITextView!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.leftBarButtonItem?.image = pointIcon("chevron.left.circle.fill")
        navigationItem.rightBarButtonItem?.image = pointIcon("checkmark.circle.fill")
      
    }

    @IBAction func back(_ sender: Any) {
        navigationController?.popViewController(animated: true)
    }
    
    @IBAction func done(_ sender: Any) {
        
        if !todoTextView.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty{
            delegate?.didAdd(name: todoTextView.text)
        }
        
        navigationController?.popViewController(animated: true)
    }
    
}

 测试一下:

 

 10.传值后在首页显示已新增的待办事项.

TodosViewController:

import UIKit

class TodosViewController: UITableViewController {
    
    
    var todos = [
        Todo(name: "学习iOS课程的基础课", checked: false),
        Todo(name: "学习iOS课程的零基础赏月App开发", checked: true),
        Todo(name: "学习iOS课程的零基础木琴App开发", checked: false),
        Todo(name: "学习iOS课程的零基础和风天气App开发", checked: false),
        Todo(name: "学习iOS课程的零基础待办事项App开发", checked: false),
        Todo(name: "学习iOS课程的小红书App开发", checked: false)
    ]

    override func viewDidLoad() {
        super.viewDidLoad()
        
        navigationItem.rightBarButtonItem?.image = pointIcon("plus.circle.fill")

        // 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
    //配置TableView的一些数据

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1   //总共有1个分类
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return todos.count   //总共有10个待办事项
    }

    
    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.todoLable!
        let initSelected = todos[indexPath.row].checked

//        // Configure the cell...
//        //配置主标题的文本
//        var contentConfiguration = cell.defaultContentConfiguration()
//        contentConfiguration.text = "昵称"   //主标题
//        contentConfiguration.secondaryText = "个性签名"    //副标题
//        contentConfiguration.image = UIImage(systemName: "star")  //图片
//        cell.contentConfiguration = contentConfiguration

        
        checkBoxBtn.isSelected = initSelected  //将cell的是否被选中属性改为todos的当前行的checked属性
        todoLabel.text = todos[indexPath.row].name
        todoLabel.textColor = initSelected ? .tertiaryLabel : .label   //三元运算符.根据是否被选中进行判断,如果被选中的话变成浅色,未被选中就是原来的Lable Color.
        
        cell.checkBoxBtn.addAction(UIAction(handler: { action in
            self.todos[indexPath.row].checked.toggle()    //如果check原来是true,被点击之后就进行取反,变成false.
            let checked = self.todos[indexPath.row].checked
            checkBoxBtn.isSelected = checked
            todoLabel.textColor = checked ? .tertiaryLabel : .label
            
        }), for: .touchUpInside)
        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 func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {

    }
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: 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?) {
        if segue.identifier == kAddTodoID{
            let vc = segue.destination as! TodoTableViewController
            vc.delegate = self
        }
    }
    

}

extension TodosViewController: TodoTableViewControllerDelegate{
    func didAdd(name: String){
        todos.append(Todo(name: name, checked: false))
        tableView.insertRows(at: [IndexPath(row: todos.count - 1, section: 0)], with: .automatic)
        
    }
}

 启动测试:

 11.实现用户输入新增待办事项时实时换行.

将Todo Text View Ctrl拖拽到添加待办事项这里,选择delegate.

 TodoTableViewController:

import UIKit

protocol TodoTableViewControllerDelegate{
    func didAdd(name: String)
}

class TodoTableViewController: UITableViewController {
    
    var delegate: TodoTableViewControllerDelegate?
    
    @IBOutlet weak var todoTextView: UITextView!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.leftBarButtonItem?.image = pointIcon("chevron.left.circle.fill")
        navigationItem.rightBarButtonItem?.image = pointIcon("checkmark.circle.fill")
      
    }

    @IBAction func back(_ sender: Any) {
        navigationController?.popViewController(animated: true)
    }
    
    @IBAction func done(_ sender: Any) {
        
        if !todoTextView.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty{
            delegate?.didAdd(name: todoTextView.text)
        }
        
        navigationController?.popViewController(animated: true)
    }
    
}


extension TodoTableViewController: UITextViewDelegate{
    func textViewDidChange(_ textView: UITextView) {
        //将Table View重新布局
        tableView.performBatchUpdates {
            //不需要放任何东西就可以自动刷新布局
        }
    }
}

测试: