tsc036
tsc036

Reputation: 1

UITableView Cell not added below bottom of the screen

I'm trying to dynamically insert rows into a UItableview to allow users to input a list. Inserting new rows works until I get to the bottom of the tableview. When I reach the bottom my fatal error triggers because the cell is the wrong type, this seems to be caused by the insert statement not being executed.

Here is my code for the tableview:

//
//  TextEntryViewController.swift
//  GroceryPlanner
//
//  Created by Taygan Caldwell on 1/18/19.
//  Copyright © 2019 None. All rights reserved.
//

import UIKit

class TextEntryViewController: UIViewController,UITextFieldDelegate,UITableViewDataSource,UITableViewDelegate {
    //MARK: Properties
    @IBOutlet weak var save: UIBarButtonItem!
    @IBOutlet weak var tableView: UITableView!
    var enteredItems=[String]()
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource=self
        tableView.delegate=self
        // Do any additional setup after loading the view.
        updateSaveButton()
    }
    //MARK: TableView Methods
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return enteredItems.count+1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellIndentifier="InputTableViewCell"
        guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIndentifier, for: indexPath) as? InputTableViewCell else{
            fatalError("wrong cell type")
        }
        cell.input.delegate=self
        cell.input.tag=indexPath.row
        if indexPath.row < enteredItems.count{
            cell.input.text=enteredItems[indexPath.row]
        }
        return cell
    }
    //MARK: UITextFieldDelegate
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        let indexPath=IndexPath(row:enteredItems.count ,section:0)
        tableView.insertRows(at: [indexPath], with: .automatic)
        guard let cell=tableView.cellForRow(at: indexPath) as? InputTableViewCell else{
            fatalError("wrong cell type")
        }
        cell.input.becomeFirstResponder()
        return true
    }
    func textFieldDidEndEditing(_ textField: UITextField) {
        textField.resignFirstResponder()
        if textField.text != ""{
            enteredItems.insert(textField.text!, at: enteredItems.count)
        }
        //refresh table
        /*
        self.tableView.reloadData()
        let cell=getCell(enteredItems.count)
        if cell.input.text != ""{
            cell.input.text=""
        }
        */
        //enable save button if there is a least one item
        updateSaveButton()
    }
    func textFieldDidBeginEditing(_ textField: UITextField) {
        let index=textField.tag
        let cell=getCell(index)
        cell.becomeFirstResponder()
        if index < enteredItems.count{
         enteredItems.remove(at: index)
        }
    }
    //MARK: Navigation

    @IBAction func cancel(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }
    // This method lets you configure a view controller before it's presented.
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        guard let button=sender as? UIBarButtonItem, button===save else{
            print("save button not pressed")
            return
        }
    }
    //MARK: Private Methods
    private func updateSaveButton(){
        save.isEnabled = !enteredItems.isEmpty
    }
    private func getCell(_ index:Int)->InputTableViewCell{
        let indexPath=IndexPath(row: index,section:0)
        guard let cell=tableView.cellForRow(at: indexPath) as? InputTableViewCell else{
            fatalError("wrong cell type")
        }
        return cell
    }
}

Upvotes: 0

Views: 106

Answers (2)

karthik
karthik

Reputation: 631

  1. textFieldShouldReturn will be called when you press return in keyboard. then
    1. update the entered items. then
    2. insert the new row in the tableview.

Update 4. cellForRowAtIndexpath gives only the cell that is visible. 5. if tableview reaches bottom, then on every insert you have to call tableview.scrollToBottom. then you can get the cell for the last indexpath

By doing this way you will not be endup in fatal error.

Upvotes: 0

Thiago Nicolau
Thiago Nicolau

Reputation: 146

This should be executing before the method insertRows

  if textField.text != ""{
       enteredItems.insert(textField.text!, at: enteredItems.count)
  }

This method is not called when you press return func textFieldDidEndEditing(_ textField: UITextField)

Upvotes: 1

Related Questions