0

Background

I have a UITableView with a single cell. Inside the cell is a UILabel. The cell, called PickerTableViewCell, gets its UI from a xib and adds it to its subview. This is done because this xib is used by many different custom cells.

Problem

It appears that when this cell is dequeued by the table view, its width extends beyond the table views width on the right hand side.

Here is the xib with the UILabel centred within the cell, followed by how it appears on the device. Notice how the label is off-centre on the device:

centred xib centred device

When I move the label to the very right of the cell (label.trailing = pickerCell.trailing + 0), it disappears off the right hand side. Below is how that looks in the xib followed by how it appears on the device:

right xib right device

When I align the UILabel to the left of the cell (label.leading = pickerCell.leading + 0), it correctly aligns to the left on the device.

Here is how the PickerTableViewCell loads the xib:

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)


        // load the xib to associate with
        let nib = Bundle.main.loadNibNamed("PickerTableViewCell", owner: nil, options: nil)
        if let view = nib?.first as? UIView{
            self.addSubview(view)
        }
    // ...
}

Here is how the tableview registers the cell:

self.tableView.register(PickerTableViewCell.self, forCellReuseIdentifier: "pickerCell")

And finally here is how it is dequeued:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "pickerCell") as! PickerTableViewCell
        return cell
}

Could anyone help understand what is going on?? Why is my cell seeming to extend beyond the width of the table view?

Ryan
  • 948
  • 6
  • 20
  • 1
    Use constraints of label: _top, bottom, leading , trailing_ = **0** with superview and do `myLabel.textAlignment = .center` – dahiya_boy Jan 29 '19 at 06:45

2 Answers2

2

While assigning any xib, you have to specify the frame. Here is the modified code:

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    // load the xib to associate with
    let nib = Bundle.main.loadNibNamed("PickerTableViewCell", owner: nil, options: nil)
    if let view = nib?.first as? UIView{
        self.addSubview(view)
        view.frame = bounds //Provide the frame
    }
    // ...
}
Sohil R. Memon
  • 9,404
  • 1
  • 31
  • 57
  • Disagreed, here is the [post](https://stackoverflow.com/questions/25541786/custom-uitableviewcell-from-nib-in-swift) where SO's loading cell from XIB but none was giving frame to the cell and it is understandable **WHY**. – dahiya_boy Jan 29 '19 at 06:52
  • 1
    This solved it perfectly! I was pulling my hair out over this - THANK YOU! – Ryan Jan 29 '19 at 06:53
  • @dahiya_boy I don't think so, try in your case and let me know ;) I am here to know your answer :D – Sohil R. Memon Jan 29 '19 at 06:54
  • @SohilR.Memon Its nice if it is working but never seen issue like this. Every time I made cell xib, all I have to do is to register it and then dequeue. For size, it automatically loads but I have to use `heightForRow` for cell height. – dahiya_boy Jan 29 '19 at 06:59
  • @dahiya_boy You are talking about different case, checkout the below answer in that no `frame` is needed but when you are initialising in `UITableViewCell` class it's must else how it will know where to sit and also you can't give the constraint to `UITableViewCell` main view. Let me know for more concern, I will be happy to help :) – Sohil R. Memon Jan 29 '19 at 07:01
  • @SohilR.Memon, OP loading cell in little bit different way. I need little more clearance for my domain. In `self.addSubview(view)`, what is **self** and **view** ?? – dahiya_boy Jan 29 '19 at 07:08
  • @dahiya_boy `self` is itself a `UITableViewCell` custom class and `view` is `UIView` which is actually a `contentView` of `nib` which we have designed in `Bundle`. Let me know, I have answered your question ;) – Sohil R. Memon Jan 29 '19 at 07:16
  • 1
    @SohilR.Memon, I directly load XIB and register it. I never done this practice (adding as a subview) as it is never required and I dont think it is a good practice bcz your xib is of `UITableviewCell`, when you use `nib?.first` it gives the cell itself as a UIView so why it needed to add as a subview. – dahiya_boy Jan 29 '19 at 07:33
  • @dahiya_boy I don't think so it's a good or not but depends on requirement and also Apple doesn't specifies it's wrong or right, so depending on your convinience you can go. Also, `UITableViewCell` itself inherits `UIView`, pls check :) – Sohil R. Memon Jan 29 '19 at 08:22
  • 1
    @SohilR.Memon, I already mentioned cell itself a `UIView` and OP adding a view from nib into it & which is somewhere undigestible for me. Rest, everyone have their own code-of-style so I can't commit anymore. BTW thanks for your explanation. – dahiya_boy Jan 29 '19 at 09:09
0

In case of using Nib for cell design, don't register the cell class itself, register the nib instead.

Remove the code

init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) 

And the registration process would be like

let cellNib = UINib.init(nibName: "YourNibName", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "Identifier")

Dequeue process is okay.

Ratul Sharker
  • 7,484
  • 4
  • 35
  • 44