带有自定义单元格的 UITableView 弹出窗口失败,单元格属性始终为零

UITableView popover with custom cell fails with cell attributes always nil

我正在尝试显示带有自定义单元格的 UITableView 弹出窗口,但单元格中的 UILabel 出口始终为零。我使用故事板创建了弹出窗口和自定义单元格。一切似乎都正确连接,我的自定义单元格具有 "Cell" 标识符。弹出窗口显示正确,只是自定义单元格中的标签不会设置,因为它们为零。

我尝试使用 Apple 方法(请参阅下面的 buttonPressed 函数)和 中建议的 segue 方法来呈现弹出窗口,但都没有解决我的问题。

我的自定义 UITableViewCell class 有两个连接的标签和一个未连接的 int。所有故事板连接似乎都有效:

class PopoverTableCell : UITableViewCell {
   @IBOutlet var label1: UILabel!   // <== connected in storyboard
   @IBOutlet var label2: UILabel!   // <== connected in storyboard

   var int3 : Int? = nil
}

这是我从视图控制器(通过按钮按下)呈现它的方式(Apple 的方法):

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.
   }

}

这成功打开了弹出窗口,但是当我尝试在单元格中设置标签时,它失败了,因为标签始终为零。

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
   }

}

我在 cellForRowAt 基金的 return 语句上设置了一个断点,我在调试器中得到了这个:

Debugger Image

无论我做什么,label1 和 label2 插座始终为零,但 int3(不是插座)似乎工作正常。

您不需要注册单元格,因为您在故事板中创建了单元格。我还想解释错误: In error Int is working fine but UILabel are nil,原因是没有加载 UILabel(任何视图)。

我认为此评论中描述的问题:

  // if I don't register, the cell fails to deque

零出口是同一问题的症状。

如果您在故事板中创建出口,它们将无法通过默认 init() 方法正确初始化,这是您在使用 PopoverController() 创建视图控制器时使用的方法。

尝试在故事板中为您的视图控制器指定一个标识符:

然后像这样实例化它:

  let popoverController = storyboard?.instantiateViewController(withIdentifier: "MyViewController") as! PopoverController

在这种情况下,单元格应该从故事板中拉取(准确地说,它通过 init?(coder aDecoder: NSCoder) 方法而不是 init() 运行),因此它们的出口不会为零。如果您以这种方式实例化视图控制器,您也不需要注册单元格。