kitchen800
kitchen800

Reputation: 227

Passing data via delegate to UITableView

I been trying to get my head around passing data to various view controllers over the last few days. I jumped in a bit too too deep at the start and got very confused. Finally I think I have sorted. However I cannot see where I have gone wrong below. I am close but think i have gone blind from trying so much over the weekend. Looked at callbacks but I think delegates make more sense to me.

I have 2 view controllers. One with a UITableView and one where the data get inputted via text field. I have no errors. However the input prints in viewcontroller 2 but does not show up in the UITableView. Finding it hard to see what I've done wrong.

VC1:

import Foundation
import UIKit


private let reuseidentifier = "Cell"

//here
struct Contact {
var fullname: String
}





class ContactController: UITableViewController {

var contacts = [Contact]()


override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?.navigationBar.prefersLargeTitles = true
    self.navigationItem.title = "Contacts"

    self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(handleAddContact))
    view.backgroundColor = .white
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: reuseidentifier)
}

@objc func handleAddContact () {

    //here
    let controller = AddContactController()
    controller.delegate = self

    self.present(UINavigationController(rootViewController: controller), animated: true, completion: nil)
}


//UITABLEVIEW
override func numberOfSections(in tableView: UITableView) -> Int {
    return contacts.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: reuseidentifier, for: indexPath)
    cell.textLabel?.text = contacts[indexPath.row].fullname
    return cell
}

}

  //here
  extension ContactController: AddContactDelegate {

func addContact(contact: Contact) {
    self.dismiss(animated: true) {
        self.contacts.append(contact)
        self.tableView.reloadData()
    }
}

}

My VC2 where data gets inputted

import Foundation
import UIKit

//here
protocol AddContactDelegate {
func addContact(contact: Contact)
 }

 class AddContactController: UIViewController {


//here
var delegate: AddContactDelegate?

let textField: UITextField = {
    let tf = UITextField()
    tf.placeholder = "Full Name"
    tf.textAlignment = .center
    tf.translatesAutoresizingMaskIntoConstraints = false
    return tf
}()

override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = .white


   self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(handleDone))

    self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(handleCancel))

    view.addSubview(textField)
    textField.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    textField.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    textField.widthAnchor.constraint(equalToConstant: view.frame.width - 64).isActive = true

    textField.becomeFirstResponder()

}

//here
@objc func handleDone(){
print("done")

    guard let fullname = textField.text, textField.hasText else {
        print("handle error here")
        return
    }

    let contact = Contact(fullname: fullname)
    delegate?.addContact(contact: contact)
    print(contact.fullname)
}


@objc func handleCancel(){
    self.dismiss(animated: true, completion: nil )
}

}

Upvotes: 0

Views: 47

Answers (2)

Shehata Gamal
Shehata Gamal

Reputation: 100503

There is no problem with your delegate implementation , You need to implement numberOfRowsInSection and return 1

override func numberOfSections(in tableView: UITableView) -> Int {
     return contacts.count
}       
override func tableView(_ tableView: UITableView, 
      numberOfRowsInSection section: Int) -> Int {
    return 1
 }

Or think if you really need this only

override func tableView(_ tableView: UITableView, 
      numberOfRowsInSection section: Int) -> Int {
    return contacts.count
}

Upvotes: 1

DevKyle
DevKyle

Reputation: 1091

I believe protocol is implemented properly. Only thing I see is you are adding contacts after vc2 is dismissed as part of completion handler. Place the code before calling dismiss:

In func addContact()

contacts.append(contact)
tableView.reloadData()
dismiss()

Upvotes: 0

Related Questions