1

I send a parameter from my viewController to customCell. My custom cell has a textField. In my viewController I have a string variable for storing the value in textField, because this value I will send to a rest services.

MyCustomCell

customCell: TableViewCell: {
 var data: String?
 @IBOutlet weak var textField: UITextField!

 override func awakeFromNib() {
  super.awakeFromNib()
  textField.delegate = self
 }

 func setData(data: inout String) {
  self.data = data
 }
}

extension customCell: UITextFieldDelegate {
 func textFieldDidEndEditing(_ textField: UITextField) {
  data = textField.text ?? ""
 }
}

MyViewController

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! customCell
  cell.setData(data: &data.email)
  return cell
}

When I sent the reference to the customCell, I lost the reference in the textFieldDidEndEditing method.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Joseph
  • 97
  • 3
  • 9

2 Answers2

2

Don't do that.

Create a data model using a class. A class is reference type

class Model {

    var name : String   
    var email : String

    init(name: String, email: String) {
        self.name = name
        self.email = email
    }
}

Declare the data source array

var models = [Model]()

In the cell declare a property of the model (by the way class names start with a capital letter)

class CustomCell: TableViewCell {

    @IBOutlet weak var textField: UITextField!

    var model: Model! {
       didSet {
          textField.text = model.email
       }
    }

    override func awakeFromNib() {
       super.awakeFromNib()
       textField.delegate = self
    }
}


extension CustomCell: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField) {
        model.email = textField.text ?? ""
    }
}

In cellForRow pass the model to the cell

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomCell
     cell.model = models[indexPath.row]
     return cell
}

Due to the reference semantics the value in the model is preserved.

vadian
  • 274,689
  • 30
  • 353
  • 361
1

The following is not doing what you think it is:

func setData(data: inout String) {
    self.data = data
}

Sure, the String you passed to this method is inout, but this doesn’t change the fact that your cell’s String property is a value type and thus your self.data becomes, effectively, a new instance.

Fundamentally, you’re trying to achieve reference type semantics with String, which is a value type.

You can contort yourself to achieve this, but I’d discourage you from attempting to do so. It’s going to be cleaner to adopt a closure or protocol-delegate or reactive pattern for the cell to notify the view controller or the model of the change.

Rob
  • 415,655
  • 72
  • 787
  • 1,044