I'm trying to present a UITableView popover with custom cells but the UILabel outlets in my cell are always nil. I used the storyboard to create the popover tableview and the custom cell. Everything seems connected correctly and my custom cell has the "Cell" identifier. The popover shows correctly, it's just that the labels in the custom cells won't set because they are nil.
I have tried presenting the popover using the Apple method (see the buttonPressed func below) and the segue method suggested in UITableViewCell's attributes are nil when instantiating UITableView as a popover but neither fixed my problem.
My custom UITableViewCell class has two connected labels and one unconnected int. All storyboard connections seem valid:
class PopoverTableCell : UITableViewCell {
@IBOutlet var label1: UILabel! // <== connected in storyboard
@IBOutlet var label2: UILabel! // <== connected in storyboard
var int3 : Int? = nil
}
Here's how I present it (Apple's method) from the view controller (via button push):
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
@IBAction func buttonPressed(_ sender: UIButton) {
let popoverController = PopoverController()
popoverController.modalPresentationStyle = UIModalPresentationStyle.popover
popoverController.preferredContentSize = CGSize(width: 200, height: 300)
present(popoverController, animated: true, completion: nil)
let popoverPresentationController = popoverController.popoverPresentationController
popoverPresentationController?.sourceView = sender
popoverPresentationController?.sourceRect = CGRect(x: 0, y: 0, width: sender.frame.size.width, height: sender.frame.size.height)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
That successfully brings up the popover but when I try to setup the labels in the cell, it fails because the labels are always nil.
class PopoverController : UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// it makes no difference if I set these or not - storyboard does it for me
self.tableView.delegate = self
self.tableView.dataSource = self
// if I don't register, the cell fails to deque
self.tableView.register(PopoverTableCell.self, forCellReuseIdentifier: "Cell")
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! PopoverTableCell
cell.backgroundColor = UIColor.yellow
cell.label1?.text = "Label 1111"
cell.label2?.text = "Label 2222"
cell.int3 = 5555
print("label1: \(cell.label1)") // <== always nil
print("label2: \(cell.label2)") // <== always nil
print("label3: \(cell.int3)") // <== always Optional(5555) which is correct
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
}
I put a breakpoint on the return statement of the cellForRowAt fund, I get this in the debugger:
No matter what I do, the label1 and label2 outlets are always nil but the int3 (not an outlet) seems to work just fine.