Search code examples
iosswiftxcodeuitableviewrealm

Saving user input from repeating Text Fields in table View?


I am trying to code a notecard app that allows the user to type in terms and definitions when creating each notecard (I am coding this in Swift). I created a table view of notecards where the user can type in the term and definition for each notecard. I am saving their data through Realm. Currently, I am able to save the number of notecards they add. However, I am having trouble figuring out how to save their input for the term and definition of each note card (I ask for user input through a text field for the term and a text field for the definition). Because I had to create another class for the UITableViewCell (to avoid the outlets cannot be connected to repeating content error), I cannot access the termTextField and defTextField inside my CreateNewSetTableViewController, and therefore cannot save or do anything to user data. Any help would be much much appreciated, I have been trying to work this out for about 2 days now. Thank you so much :)

import UIKit
import RealmSwift


class NotecardTableViewCell: UITableViewCell {
    @IBOutlet weak var termTextField: UITextField!
    @IBOutlet weak var defTextField: UITextField!
}


class CreateNewSetTableViewController: UITableViewController {
    var noteCards: Results<Notecard>?
    let realm = try! Realm()
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.separatorStyle = .none
        loadNotecards() //load up all the categories currently owned
    }
    

    //MARK: - Navigation Bar Methods
    
    @IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
        let newItem = Notecard()
        newItem.term = "wooho"
        newItem.def = "asdf"
        self.save(notecard: newItem)
        tableView.reloadData()
    }
    
    @IBAction func doneButtonPressed(_ sender: UIBarButtonItem) {
        _ = navigationController?.popToRootViewController(animated: true)
    }
    
    
    //MARK: - Data Manipulation Methods
    
    func save(notecard: Notecard){
        do {
            try realm.write{
                realm.add(notecard)
            }
        }
        catch{
            print (error)
        }
        tableView.reloadData()
    }
    
    func loadNotecards(){
        noteCards = realm.objects(Notecard.self)
        tableView.reloadData()
    }
    
    // MARK: - Table view data source
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return noteCards?.count ?? 1
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "NotecardCell", for: indexPath) as! NotecardTableViewCell
        return cell
    }
    
}

Solution

  • You can retrieve in some different ways:

    1. Accessing the cell value and downcasting to your cell's type:

      @IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
          guard let cell = tableView.cellForRow(at: indexPath) as? NotecardTableViewCell else { return }
          let newItem = Notecard()
          newItem.term = cell.termTextField.text
          newItem.def = cell.defTextField.text
          self.save(notecard: newItem)
          tableView.reloadData()
      }
      

    I wouldn't recommend this way because if the cell is not being displayed, you won't retrieve the correct value, since it's being reused.

    1. You can set tags to the UITextFields andd access the textField input through the delegate UITextFieldDelegate:

      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
          let cell = tableView.dequeueReusableCell(withIdentifier: "NotecardCell", for: indexPath) as! NotecardTableViewCell
          cell.termTextField.delegate = self
          cell.termTextField.tag = 0 // Tag was set to demonstrate how it works, you can set it as the indexPath.row
          cell.defTextField.delegate = self
          cell.defTextField.tag = 1
          return cell
      }
      
      
      func textFieldDidEndEditing(_ textField: UITextField) -> Bool {
           if textField.tag == 0 { 
           // Retrieve Term text
           } else if textField.tag == 1 {
           // Retrieve def text
           }
      }