1

I've got a UITableViewController with two custom cells - one contains a UITextField (for the user to input a title) and the other contains a UITextView (for the user to input a description). Whenever these change, I want to update my memory object (which is a struct with two variables - memoryTitle and memoryDescription).

The memoryTitle seems simple enough - on my ViewController I have the following:

 @IBAction func memoryTitleChanged(_ sender: UITextField) {
        memory.memoryTitle = sender.text ?? ""
    }

The UITextView has confused me slightly though. There's two issues I'm having - I can't create an action in the same way I can for the UITextField, so my next thought was to make the ViewController the delegate and use textViewDidChange to update memory.memoryDescription but that brings me to my second problem.

In order to make the UITextView cell resize dynamically, I used the following tutorial which works perfectly (https://medium.com/@georgetsifrikas/embedding-uitextview-inside-uitableviewcell-9a28794daf01) to make my custom cell this:

class DetailTextTableViewCell: UITableViewCell, UITextViewDelegate {

    //Found below method for resizing UITextView and cell - https://medium.com/@georgetsifrikas/embedding-uitextview-inside-uitableviewcell-9a28794daf01
    @IBOutlet weak var memoryDescriptionTextView: UITextView!
    var textChanged: ((String) -> Void)?

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        memoryDescriptionTextView.delegate = self
        memoryDescriptionTextView.backgroundColor = UIColor.red
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

    //Found below method for resizing UITextView and cell - https://medium.com/@georgetsifrikas/embedding-uitextview-inside-uitableviewcell-9a28794daf01
    func textChanged(action: @escaping (String) -> Void) {
        self.textChanged = action
    }

    func textViewDidChange(_ textView: UITextView) {
        textChanged?(textView.text)
    }
}

Now I'm stuck with DetailTextTableViewCell being the UITextView's delegate, so I'm not sure how to make it update my memory object in the ViewController when the text changes. If anyone has any ideas or guidance it'd be much appreciated!

Thank you in advance.

AtulParmar
  • 4,358
  • 1
  • 24
  • 45
ADB
  • 591
  • 7
  • 21
  • from the code it seems like you have a closure `textChanged` which will be invoked on the text changes. So I believe you will be assigning value to it on cellForRow method, something like `cell.textChanged {}`. Use this closure to set value to `memory.memoryDescription` – Akhilrajtr Feb 21 '19 at 10:55

4 Answers4

1

First, you don't need textChanged method

func textChanged(action: @escaping (String) -> Void) {


Then, what you need, is assigning your textChanged closure variable (which is good approach btw) in controller's cellForRowAt for each certain cell.

Inside closure declare, that when text view did change, certain item's (from table view data source array) property will be assigned with String parameter of closure and if you need, then reload certain cell for this IndexPath

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    ...
    cell.textChanged = { text in
        self.dataSourceArray[indexPath.row].stringProperty = text
        // tableView.reloadRows(at: [indexPath], with: .none) 
            // if you want to reload row, move calling closure 
            // to `textViewDidEndEditing` instead
    }
    ...
}
Robert Dresler
  • 10,580
  • 2
  • 22
  • 40
0

Inside cellForRowAt do

let cell = /// 
cell.memoryDescriptionTextView.tag = indexPath.row
cell.memoryDescriptionTextView.delegate = self

and implement the delegate methods inside the vc

Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
0

Try to enable user interaction property of text view inside cellForRowAt method.

cell.memoryDescriptionTextView.delegate = self
cell.memoryDescriptionTextView.isUserInteractionEnabled = true
AtulParmar
  • 4,358
  • 1
  • 24
  • 45
0

declare this protocol above your cell DetailTextTableViewCell

protocol CellDelegate {
  func textViewChanged(textView : UITextView)
}

add a delegate var in your DetailTextTableViewCell

var delegate : CellDelegate?

In the cell for row of your tableView assign self to delegate property of cell

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
cell.delegate = self

}

In your DetailTextTableViewCell add this line inside textViewDidChange

 func textViewDidChange(_ textView: UITextView) {
    textChanged?(textView.text)
    delegate?.textViewChanged(textView)
}

Now implement the delegate function in your view controller

func textViewChanged(textView: UITextView) {

    }
Shahzaib Qureshi
  • 989
  • 8
  • 13