Search code examples
iosswiftuitableviewxibnib

Labels in custom TableViewCell always return their initialization values


I am fairly new to Swift and have researched the following problem extensively yet unsuccessfully.

I've created a custom TableViewCell class named ConversationCell and defined its UI in a NIB/XIB file.

XIB / NIB screenshot

 import UIKit
    import SwipeCellKit

    class ConversationCell: SwipeTableViewCell {

        @IBOutlet weak var distanceLabel: UILabel!
        @IBOutlet weak var locationLabel: UILabel!
        @IBOutlet weak var subjectLabel: UILabel!
        @IBOutlet weak var bodyLabel: UILabel!
        @IBOutlet weak var profileImageView: UIImageView!
        @IBOutlet weak var usernameLabel: UILabel!
        @IBOutlet weak var starImageView: UIImageView!
        @IBOutlet weak var dateLabel: UILabel!

        var isFollowed = false

        override func awakeFromNib() {
            super.awakeFromNib()
            // Initialization code
        }
    }

Then I wrote a simple class named Conversation that is the model class for ConversationCell.

class Conversation {
    var distance = "123 ft."
    var location = "123 Market St"
    var date = "Yesterday, 10:45AM"
    var subject = "Default subject."
    var body = "Default body"


   // var subject = "My Subject"
    //var body = "My Body"

    var username = "worldsurfer"
    var profilePhoto = UIImage(named: "profilePhoto")
}

Finally, I added a TableView that uses the custom ConversationCell to my class HomeTabViewController, which is a ViewController acting as both the source and delegate for the TableView.

Please take a look at the code below where I print the content of the labels in the cell within func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath).

Instead of returning the label values that I've defined when initializing my conversation array (i.e., "1st Conversation", "2nd Conversation", "3rd Conversation" - which get properly displayed in the TableView at runtime), it returns the default label text values that are defined in the NIB file (i.e., "The spectable before us was indeed sublime."). Simulator + Console output

import UIKit
import SwipeCellKit

class HomeTabViewController: CoreDesignViewController {
    @IBOutlet weak var tableView: UITableView!

    var conversationArray : [Conversation] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(UINib(nibName: "ConversationCell", bundle: nil), forCellReuseIdentifier: "homeTabCell")

        tableView.dataSource = self
        tableView.delegate = self


        let conversation1 = Conversation()
        conversation1.subject = "1st conversation"
        conversationArray.append(conversation1)

        let conversation2 = Conversation()
        conversation2.subject = "2nd Conversation"
        conversationArray.append(conversation2)

        let conversation3 = Conversation()
        conversation3.subject = "3rd conversation"
        conversationArray.append(conversation3)

        tableView.estimatedRowHeight = tableView.rowHeight
        tableView.rowHeight = UITableViewAutomaticDimension

        self.showNavBar()
    }

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



}

extension HomeTabViewController: UITableViewDataSource, UITableViewDelegate, SwipeTableViewCellDelegate{


    //MARK: - UITableViewDataSource Protocol Implementation
    /***************************************************************/


    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return conversationArray.count
    }

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


        guard let cell = tableView.dequeueReusableCell(withIdentifier: "homeTabCell", for: indexPath) as? ConversationCell
        else{
            fatalError("The dequeued cell is not an instance of homeTabCell.")
        }

        //To make the cell Swipeable via SwipeCellKit
        cell.delegate = self


        print("CELL_FOR_ROW_AT - indexPath.row = \(indexPath.row) | Conversation.subject = \(conversationArray[indexPath.row].subject)")

        //Initializing the cell
        cell.distanceLabel.text = conversationArray[indexPath.row].distance
        cell.locationLabel.text = conversationArray[indexPath.row].location
        cell.dateLabel.text = conversationArray[indexPath.row].date
        cell.subjectLabel.text = conversationArray[indexPath.row].subject
        cell.bodyLabel.text = conversationArray[indexPath.row].body
        cell.usernameLabel.text = conversationArray[indexPath.row].username
        cell.profileImageView.image = conversationArray[indexPath.row].profilePhoto

        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {


        guard let cell = tableView.dequeueReusableCell(withIdentifier: "homeTabCell", for: indexPath) as? ConversationCell
            else{
                fatalError("The dequeued cell is not an instance of homeTabCell.")
        }
         print("DID_SELECT_ROW_AT - Selected Row = \(indexPath.row) | cell.subjectLabel.text = \(cell.subjectLabel.text!)")
 }

I've tried with all the different labels in the custom cell and same result: it always prints out the corresponding default text values of the XIB file.

Any idea why (the hell) this is happening? :) Thanks much!


Solution

  • Look what you are doing in didSelectRowAt!

    guard let cell = tableView.dequeueReusableCell(withIdentifier: "homeTabCell", for: indexPath) as? ConversationCell
        else{
            fatalError("The dequeued cell is not an instance of homeTabCell.")
    }
    

    You are dequeuing a new cell! The cell returned from dequeueReusableCell is always the same as the one you designed in the XIB file.

    Instead of dequeuing a new cell, you should get the cell in the table view that corresponds to the index path:

    let cell = tableView.cellForRow(at: indexPath)
    // print cell contents...
    

    Or just access the array that you've got:

    let conversation = conversationArray[indexPath.row]
    // print conversation's properties...