0

I have a tableView with dynamic cells with multiple TextViews. I am dismissing a keyboard with a "Cancel" and trying to determine which TextView is being dismissed to "undo" the changes made by user.

Based on this similar question: How to determine which textfield is active swift I have adapted one of the answers for the following extension:

extension UIView {
var textViewsInView: [UITextView] {
    return subviews
        .filter ({ !($0 is UITextView) })
        .reduce (( subviews.compactMap { $0 as? UITextView }), { summ, current in
            return summ + current.textViewsInView
        })
}
var selectedTextView: UITextView? {
    return textViewsInView.filter { $0.isFirstResponder }.first
}
}

This is working and I am presently testing in the following code:

   @objc func cancelButtonAction() {
    if let test =  tableView.selectedTextView {
        print("View Found")
    }
    tableView.beginUpdates()
    tableView.endUpdates()
}

Doing a break at print("View Found") I can inspect "test". The following is the result.

enter image description here

This appears to only identify the view Test by a memory address. My question is how do I interpret this to identify the view that was being edited?

Update: There seems to be some issue in understanding. Assume I have a table with two cells and in each cell two textViews (dynamic cells). Assume the table loads by saying in the 4 textViews. "Hi John", "Hi Sam", "Bye John", "Bye Sam". Suppose the user starts editing a cell and changes one cell to read "Nachos". Then the user decides to cancel. I want to then replace with the value that was there before (from my model). I can find the textView but it now reads "Nachos". Therefore I do not know which textView to reload with the appropriate Hi and Bye.

jz_
  • 338
  • 2
  • 14
  • I don't understand what is missing. Do you have the correct textview when you press cancel? – Mocha Nov 07 '18 at 19:58
  • Yes based on the text it is correct. However I see nothing identified I can refer to in code. – jz_ Nov 07 '18 at 20:01
  • If we have the correct textview, can't we just set the text = ""? – Mocha Nov 07 '18 at 20:04
  • Because the user can change the text -- therefore cannot test with it. – jz_ Nov 07 '18 at 20:05
  • This question does not make sense.. You already have the textView that is being dismissed when the user presses cancel. What are you trying to do? – Mocha Nov 07 '18 at 20:10
  • Ok an example. There are several TextViews. Each can be edited and I have a cancel button on the keyboard. (The keyboard is common for all TextViews). So the one demonstrated is called tagline. On cancel I would like to run code like if textView = 'tagline' { tagline.text = 'whatever was original text' – jz_ Nov 07 '18 at 20:17
  • How about using a placeholder for your textviews and then just setting the text = "" for the original text (placeholder) ? – Mocha Nov 07 '18 at 20:24
  • Sorry, I do not follow you. That does not help me find which TextView it is. Additionally, there can be multiple cells also. – jz_ Nov 07 '18 at 20:29
  • Implement a placeholder for your textviews so that when their text is empty, it will have a default value. Therefore, when a user presses cancel while in focus of a textview, we can set the textview's text to its default value. We don't need to know which textview it is because the cell that implements the placeholder will do the work. See link to implement a textview placeholder.. https://stackoverflow.com/questions/27652227/text-view-placeholder-swift – Mocha Nov 07 '18 at 20:33
  • I think I get the gist of but you need to revise your question. **I want to then replace with the value that was there before (from my model). I can find the text field but it now reads "Nachos". Therefore I do not know which textView to reload with the appropriate Hi and Bye.** First you mention text field and then you mentioned textView. These are two very different objects. Next is are you trying to update the text or placeholder of the textView? What is your "model"? – Li Sim Nov 08 '18 at 03:25

2 Answers2

0

Implement a placeholder for your textviews so that when their text is empty, it will have a default value. Therefore, when a user presses cancel while in focus of a textview, we can set the textview's text to its default value. See link to implement a textview placeholder.. Text View Placeholder Swift

Mocha
  • 2,035
  • 12
  • 29
0

I did solve this problem by adding the .tag property to the textView objects. I also dropped the extension approach and used textView delegate. The solution required me to first assign the tag and delegate = self for each textView in the tableView: cellForRowAt. The following shows one TextView of many. Notice the tag is setup so I may determine the section and the row it came from and the specific item.

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
...
  cell.directionsTextView.delegate = self
  cell.directionsTextView.tag = indexPath.section*1000 + indexPath.row+1
  return cell 
 }

Two global variables are defined in my tableView class:

   var activeTextView = UITextView()
   var activeTextViewPresentText = String()

The textViewDidBeginEditing captures the original state of the textView text before the user starts editing.

      // Assign the newly active textview to store original value and original text
func textViewDidBeginEditing(_ textView: UITextView) {
    print("textView.tag: \(textView.tag)")
    self.activeTextView = textView
    self.activeTextViewPresentText = textView.text
}

Lastly, if the user cancels the editing, the original text is reloaded.

  @objc func cancelButtonAction() {
    if  activeTextView.text != nil {
        activeTextView.text = activeTextViewPresentText
    }
    self.view.endEditing(true)
    tableUpdate()
}
jz_
  • 338
  • 2
  • 14