Micah Montoya
Micah Montoya

Reputation: 767

Swift / How to populate UITableViewCells

I have a controller with a Table View on it. Have defined my cells in a view and then I bind it to the table view. (Please excuse the terminology). App builds and runs fine but none of the labels defined in the cell show anything. Entire table is blank except for the cell separators. I've followed numerous tutorials and searched SO extensively for reasons, how to create (Create a Table View - Apple docs), settings to check, all with the same results. I've also tried cleaning, restarting Xcode, etc. This is Xcode 8/Swift 3.

The view controller has a table view and I register the cell class like so in the viewDidLoad

self.tableView.registerCellClass(MenuTableViewCell.self) 

UITableViewDataSource code

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: MenuTableViewCell.identifier, for: indexPath) as! MenuTableViewCell

    let item = menusItems[indexPath.row]
    cell.setData(item)
    return cell
}

menuItems is an array of a struct I have that is created before anything else is done

BaseTableViewCell

open class BaseTableViewCell: UITableViewCell {
class var identifier: String { return String.className(self) }

public required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    setup()
}

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    setup()
}

open override func awakeFromNib() {
}

open func setup() {
}

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

    // Configure the view for the selected state
}

open class func height() -> CGFloat {
    return 48
}

open func setData(_ data: Any?) {
    if let menuText = data as? String {
        self.textLabel?.text = menuText
    }
    if let menuImage = data as? UIImage {
        self.imageView?.image = menuImage
    }
}
}

Table View Cell code - inherits the BaseTableViewCell

class MenuTableViewCell: BaseTableViewCell {

//MARK: Properties
@IBOutlet weak var name: UILabel!
@IBOutlet weak var icon: UIImageView!

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

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    // Configure the view for the selected state
}

override func setData(_ data: Any?) {
    if let data = data as? MenuTableViewCellData {
        NSLog("menu name - %@", data.text)
        self.icon?.image = data.image
        self.name?.text = data.text
    }
}
}

All menu names are written to the debug area so the code is being executed.

I don't know if there is hook that is missing or if something else. Please let me know if anything further is also needed. Any help is appreciated.

Screenshots showing IBOutlets connected name

icon

Here is the delegate and data source from the controller

extension LeftViewController : UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return MenuTableViewCell.height()
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if let menu = LeftMenu(rawValue: indexPath.row) {
        self.changeViewController(menu)
    }
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if self.tableView == scrollView {

    }
}
}

extension LeftViewController : UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return menusItems.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: MenuTableViewCell.identifier, for: indexPath) as! MenuTableViewCell

    let item = menusItems[indexPath.row]
    cell.setData(item)
    return cell
}
}

Thanks everyone for your help. I was able to get it working. I removed the XIB file, created the layout in the view and then wired it up from there (followed here for how to).

Upvotes: 3

Views: 555

Answers (3)

Naveen Ramanathan
Naveen Ramanathan

Reputation: 2206

Can you check whether name and icon have proper constraints

Upvotes: -1

Graham Perks
Graham Perks

Reputation: 23390

You may have 0-height rows. I see a height method in there - what is calling it? Do you have an implementation of

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat

somewhere?

Are you setting the table view's rowHeight?

Upvotes: 1

Andy Obusek
Andy Obusek

Reputation: 12832

Verify that you've connected the IBOutlets for name and icon in MenuTableViewCell. Assuming what you say is true, that the NSLog in setData is called, chances are you haven't connected the IBOutlets for the table view cell subclass.

Upvotes: 3

Related Questions