BSK-Team
BSK-Team

Reputation: 1810

Update object of an array in UIViewController from UITableViewCell

I have a UITableViewCell that I use in several UITableView's that are in differents UIViewController's. From my cell, there is an object that I update but I would like to update it also in the array of my controllers. How ?

For example :

UITableViewCell :

class NotificationTableViewCell: UITableViewCell {

    @IBOutlet weak var buttonRead: UIButton!

    var notification = Notification()

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    @IBAction func clickButtonRead(_ sender: Any) {
        self.notification.isRead = true
    }
}

UIViewController :

class NotificationsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITabBarControllerDelegate {

    @IBOutlet weak var tableView: UITableView!

    /* List notifications */
    var listNotifications = [Notification]()

    override func viewDidLoad() {
        super.viewDidLoad()

        //View cell
        let nib = UINib(nibName: "viewNotificationTableViewCell", bundle: nil)
        self.tableView.register(nib, forCellReuseIdentifier: "cellNotification")

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        var cell = tableView.dequeueReusableCell(withIdentifier: "cellNotification", for: indexPath) as! NotificationTableViewCell

        cell.notification = self.listNotifications[indexPath.row]

        return cell
    }
}

EDIT : I can pass the controller and the indexPath to the cell for update the object notification in listNotifications like this : self.controller.listNotifications[indexPath.row] = self.notification But if i use this cell with more controllers, I must cast the controller from cell to know what controller is it. I am looking for a way to update the object without having to cast the controller.

Upvotes: 1

Views: 185

Answers (2)

Irshad Ahmad
Irshad Ahmad

Reputation: 1383

You can achieve this by using protocol make a protocol in your tableview Cell Class

    protocol NotificationDelegate{
       func didReadNotification(notification:Notification , index:Int)
    }
    class NotificationTableViewCell: UITableViewCell {

        @IBOutlet weak var buttonRead: UIButton!
        // and make this optional don't initialize it
        var notification:Notification?
        var delegate:NotificationDelegate?
        var indexOfNotification:Int?
        override func awakeFromNib() {
            super.awakeFromNib()
        }

        @IBAction func clickButtonRead(_ sender: Any) {
            self.notification?.isRead = true
            self.delegate?.didReadNotification(notification:self.notification! , index:indexOfNotification!)
        }

}

and add NotificationDelegate in you ViewController

    class NotificationsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITabBarControllerDelegate , NotificationDelegate {

        @IBOutlet weak var tableView: UITableView!

        /* List notifications */
        var listNotifications = [Notification]()

        override func viewDidLoad() {
            super.viewDidLoad()

            //View cell
            let nib = UINib(nibName: "viewNotificationTableViewCell", bundle: nil)
            self.tableView.register(nib, forCellReuseIdentifier: "cellNotification")

        }

        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }

        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }

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

        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

            var cell = tableView.dequeueReusableCell(withIdentifier: "cellNotification", for: indexPath) as! NotificationTableViewCell

            cell.notification = self.listNotifications[indexPath.row]
            cell.delegate = self
            cell.indexOfNotification = indexPath.row
            return cell
        }

      // This Delegte method will be called whenever user read the notification
      func didReadNotification(notification:Notification , index:Int){
          // do what ever you want here is your index and notification..
          let notification = listNotifications[index] // this is your notification in listNotifications 
      }

}

Upvotes: 1

Jasveer Singh
Jasveer Singh

Reputation: 374

The ideal way to do it is you create a NotificationTableViewCellDelegate and set the delegate to view controller. In your method clickButtonRead call the delegate method and update the object in the view controller.

    protocol NotificationTableViewCellDelegate {
        func enableReadForNotification(notification: Notification)
    }    

    class NotificationTableViewCell: UITableViewCell {

            @IBOutlet weak var buttonRead: UIButton!
            var notification = Notification()
            weak var delegate: NotificationTableViewCellDelegate?

            override func awakeFromNib() {
                super.awakeFromNib()
            }

            @IBAction func clickButtonRead(_ sender: Any) {
                self.notification.isRead = true
               if let delegate = self.delegate {
                  delegate.enableReadForNotification(self.notification)
               }
            }
        }

Hope this helps!

Upvotes: 2

Related Questions