ios learning notes 03 todo app (use of tableview, simple storage of UserDefaults)

lebus tutorial 03

p58-66:Todos app

  • p58 create a new todos project
  • Add the tableViewController to the project, set it as the starting page, and add the corresponding class
  • Divide the project into mvc mode and view the method of tabelview controller
  • p58: cell specifies a class, and generates the cell of the specified identifile through the method
  • Let cell = tableview.dequeuereusablecell (with identifier: "todo", for: indexpath) as! Todoscell / / reuse cell
  • Then add the label control to the cell and select the type.
  • Create a class of table cell and bind it to the view
  • Make variable declaration and pull the view variable into the code.
  • Send the data to the interface
  • Define the model class, you can use the structure, after the structure initialization is completed
  • Define the data, dynamically change the value of each row according to the data, and the total number of rows
  • Write the response function after the user clicks:
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        todos[indexPath.row].isChecked = !todos[indexPath.row].isChecked // Modify whether the property in the data is missed
        let cell = tableView.cellForRow(at: indexPath) as! TodosCell // Acquired cell clicked
        cell.checkMark.text = todos[indexPath.row].isChecked ?"√":"" //Change view
        tableView.deselectRow(at: indexPath, animated: true)// Cancel Click
  • Add a view about adding tasks, use navigation viewCongtroller to realize page stack pressing and output effect, and use show function to jump pages
  • In the navigation ViewController, the navigation bar determines the maximum title block, and then to customize the title block size in the following page title block, you need to add the navigation item
  • If you need to add a button in the title bar: add control: BarButtonItem
  • Realize the function of adding tasks:
  • Use protocol and delegaate to realize reverse value transfer, which is the name of the new task
  • By using the delegation mode, the implementation is in the todos interface, which is first added to the model, and then rewritten and added to the view.
  • The first response, after the interface is loaded, transfers the response directly to the input box, and uses the navigationController after clicking the defect. pop out the current interface;
// Bind delegate
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "addTodo"{
            let vc = segue.destination as! AddTodoVC
            vc.delegate = self

    //First response:
    // sava click function
        @IBAction func saveTodo(_ sender: Any) {
        if let name = todoInputTX.text{
        delegate?.addTodo(name: name)
        navigationController?.popViewController(animated: true)
    //Implement delegate function
        func addTodo(name: String) {
        todos.append(Todo(todo: name, isChecked: false))//Add data to the model.
        let indexPath = IndexPath(row: todos.count-1, section: 0)
        tableView.insertRows(at: [indexPath], with: .automatic)//Add a new todo Rows

Note: if the interface is not consistent with the expectation after editing, check the operation code to see if you want to modify the interface. That is, first use the storyboard to render the interface, and then use the code to modify the interface.

  • Implement the modification task:
  • Pull the Accessory action of tableView Cell and drag show to another page (add and modify)
  • Assign id to segue
  • Forward value transfer: transfer the value of the cell to which you click to the modified interface and change it in the prepare function
  • Select the segue with the specified id to write the function in it, and transfer the value to the modification interface. If there is a value in the past, modify the interface name
  • In addition, improve the operation of reverse value transfer. The user clicks to go to another agent route, and then binds the agent
  • In another agent route, save it to the model, find the corresponding cell, and update the view.
// Another segue path, passing values in the past
else if segue.identifier == "editTodo"{
            let vc = segue.destination as! AddTodoVC
            vc.delegate = self//Proxy binding
            let cell = sender as! TodosCell
            let indexPath = tableView.indexPath(for: cell)!
            editRow = indexPath.row
            vc.editName = todos[editRow!].todo//Transfer parameters
// To implement the edit proxy function:
func editTodo(name: String) {
        todos[editRow!].todo = name//
        let indexPath = IndexPath(row: editRow!, section: 0)
        let cell = tableView.cellForRow(at: indexPath) as! TodosCell
        cell.todoLabel.text = todos[editRow!].todo
//If you want to jump from edit, modify the title, and click save to execute another agent:
  if editName != nil{
            navigationItem.title = "Edit Todo"
      if let name = todoInputTX.text{
            if editName != nil {
                delegate?.editTodo(name: name)//Take this agent
                delegate?.addTodo(name: name)
  • p64
  • Find the code to delete a row, and then add the operation to delete data from the model;
  • In this way, the left stroke is deleted,
  • Write the right bar button item in the code as an edit item
  • Then go to the storyboard and select tableview Editing to batch select, and modify the click event under non edit conditions.
  • Modify the default Chinese character. One is title for delete.
  • One is to modify the title of the display button through the edit function
//Delete a row to realize left sliding deletion
     override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
     if editingStyle == .delete {
        todos.remove(at: indexPath.row)//Delete data from model
     // 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
//Modify the text displayed when deleting:
    override func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
        return "delete"
// Add editing btn to the code, and modify the displayed title:
self.navigationItem.leftBarButtonItem = self.editButtonItem
        editButtonItem.title = "edit"
    override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: animated)
        editButtonItem.title = isEditing ? "complete" : "edit"

  • p65
  • To batch delete, add a delete button, pull out an action, and detect all selected cell s
  • Then for loop to delete data, and tableview.delete(), batch delete row
  • Move cell, moveRowAt method, first delete and then insert mobile data, then
  • Use the tableView.moveRow() method to move row
// Bulk delete:
 @IBAction func deleteRows(_ sender: Any) {
        if let indexPaths = tableView.indexPathsForSelectedRows{
            for indexPath in indexPaths{
                todos.remove(at: indexPath.row)
            }//This method is not safe to delete data
            tableView.beginUpdates()//Improve update performance
            tableView.deleteRows(at: indexPaths, with: .automatic)// Delete rows in batch
            tableView.endUpdates()//Improve update performance
// Mobile rows
    override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
        // Model move data
        let from = todos.remove(at: fromIndexPath.row)
        todos.insert(from, at: to.row)
        // view to move
        tableView.moveRow(at: fromIndexPath, to: to)

  • View the appDelegate file, view the life cycle functions of the app, and understand the call order
  • It is stored locally, encoded first, and then stored in the sandbox. It is defined as a function. After each data update, it is called
  • Decoding, continue in viewidload()
  • Define an empty array, another way to write an empty dictionary:
// Code, stored in the local plist:
    func saveData(){
            let data = try JSONEncoder().encode(todos) 
            //Save to local, key is "todos"“
            UserDefaults.standard.set(data, forKey: "todos")
// Fetching data from local storage
        if let data = "todos"){
            do {
                // Data is decoded into classes.
                todos = try JSONDecoder().decode([Todo].self, from: data)
//Define an empty array, another way to write an empty dictionary:
var todos = [Todo]()
var dic = [String:String]()
Published 38 original articles, won praise 0, visited 5016
Private letter follow

Tags: Mobile

Posted on Mon, 03 Feb 2020 05:01:28 -0800 by PoOP