Swift TableViewCell xib没有约束

我有两个TableView ,当我devise原始的时候,我使用故事板中的原型单元格来devise它,为了使它可重用,我尝试将它拉出到一个.xib并加载它。 当它从cellID.xib加载的时候,它会在运行时丢失所有的约束条件,而且所有的约束都是相互重叠的。

TableViewController

 let cellIdentifier = "cellID" override func viewDidLoad() { super.viewDidLoad() tableView.register(UINib(nibName: cellIdentifier, bundle: nil), forCellReuseIdentifier: cellIdentifier) tableView.rowHeight = UITableViewAutomaticDimension tableView.estimatedRowHeight = 300 } 

Storyboard中的原型单元格(用于工作)

原型电池

复制粘贴到XIB时的单元格

xib细胞

约束

对细胞的限制

XIB视图层次结构

xib视图层次结构

问题

在你的问题标题中,你问了如何解决“Swift TableViewCell xib没有约束”的问题。 另外在赏金中,你指定答案应该是:

一个适当的答案,说明为什么在移动到xib时,xib存在时约束会丢失,以及如何解决这个问题。

根据我的理解,你的问题有两个部分:

  1. 问题自定义TableViewCell xib没有约束
  2. 为什么在从Storyboard原型复制/粘贴到xib时,约束会丢失

对于问题#1,我使用了几乎所有的相同的约束,你已经显示在自定义单元格xib中的屏幕截图,它的工作。 我将在下面更详细地解释。

对于问题#2,我发现约束不会丢失。 您可能需要分享您的项目,以便其他人可以复制您遇到的问题。 我复制/粘贴了一个类似约束的故事板原型单元到一个xib,我没有任何约束的问题。 所以我可以确认复制/粘贴function是否有效。

解决scheme演示

我创build了以下演示来testing您的问题。 请参阅下面的截图。 tableView包含六个单元格。 第一和第二是相同的,有重用标识符MyCell 。 第三和第四是相同的,并有重用标识符MyCopyPasteCell 。 第五和第六是相同的,并有重用标识MyPrototypeCell

MyCell存在于xib中,几乎使用了您在屏幕截图中显示的所有相同约束。 正如你所看到的,没有约束问题。 MyCopyPasteCell使用类似的约束,从Storyboard原型复制/粘贴到xib。 MyPrototypeCell是被复制的原始原型。 即使原型被复制到xib,最后四个单元看起来完全一样。 从原型到xib的约束没有问题。

在这里输入图像说明

约束

在下面的代码中,我列出了在您的屏幕截图中为您的ContentView显示的所有约束。 (注意,我也实现了height=20aspect=1:1height=75约束,尽pipe它们没有在下面列出)。由于我没有使用它们,所以有两个约束被注释掉了。 我还添加了一个约束来replace另一个未使用的约束。

 // bottomMargin = Profile Image View.bottom + 188.5 bottomMargin = Profile Image.bottom + 17 Profile Image View.top = Username Label.top Profile Image View.leading = leadingMargin + 2 Profile Image View.top = topMargin + 20 Username Label.leading = Content Text View.leading // Username Label.top = topMargin + 20 Username Label.trailing = Content Text View.trailing Username Label.leading = Profile Image View.trailing + 15 trailingMargin = Username Label.trailing + 10 Content Text View.top = Username Label.bottom + 5 Content Text View.leading = leadingMargin + 92 bottomMargin = Content Text View.bottom + 20 

第一个注释的约束// bottomMargin = Profile Image View.bottom + 188.5没有意义,因为它会将图像的底部与单元格的底部分开188.5。 这也不符合您的故事板(用于工作)截图的原型单元格 。 我用bottomMargin = Profile Image.bottom + 17replace它, bottomMargin = Profile Image.bottom + 17用17replace了188.5。

第二个注释的约束// Username Label.top = topMargin + 20 (它将用户名和topMargin分隔20)可以在技术上工作。 然而,它的function是多余的Profile Image.top = topMargin + 20 (它分隔configuration文件图像和topMargin 20)和Profile Image View.top = Username Label.top (设置configuration文件图像和用户名相同的顶部分离即由20)。

MyTableViewController

以下是我的视图控制器。 基本上我创build了三节,每节有两个单元/行。 MyCellMyCopyPasteTableViewCell来自xib,并在viewDidLoad()中注册。 MyPrototypeCell来自Storyboard,未在viewDidLoad()注册。

 // MyTableViewController.swift import UIKit class MyTableViewController: UITableViewController { let myCell = "MyCell" let myCopyPasteCell = "MyCopyPasteTableViewCell" let myPrototypeCell = "MyPrototypeCell" override func viewDidLoad() { super.viewDidLoad() tableView.register(UINib(nibName: myCell, bundle: nil), forCellReuseIdentifier: myCell) tableView.register(UINib(nibName: myCopyPasteCell, bundle: nil), forCellReuseIdentifier: myCopyPasteCell) tableView.rowHeight = UITableViewAutomaticDimension tableView.estimatedRowHeight = 300 } // MARK: - Table view data source override func numberOfSections(in tableView: UITableView) -> Int { return 3 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 2 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if indexPath.section == 0 { let cell = tableView.dequeueReusableCell(withIdentifier: myCell, for: indexPath) return cell } else if indexPath.section == 1 { let cell = tableView.dequeueReusableCell(withIdentifier: myCopyPasteCell, for: indexPath) return cell } else { let cell = tableView.dequeueReusableCell(withIdentifier: myPrototypeCell, for: indexPath) return cell } } } 

Github链接

https://github.com/starkindustries/TableViewCellConstraintsTest

问题和解决scheme

您可能已经禁用了您的XIB的Autolayout将其ON ,从右上angular的菜单转到File Inspector

在这里输入图像说明

你可以按照简单的步骤从Xib创build单元格

1.用.xib创buildUITableCell (✅也创buildXib文件) 在这里输入图像说明

2.给出小区标识符

在这里输入图像说明

3.布局约束

🔸ImageView提供从Left和下angular高度常数和长宽比[我已设置边框显示框架]

🔸 title lable UIlable来自TopLeftRight三个方面的限制。NumberOflines NumberOflines=0 (🚫不要给高度常量 – 如果给出警告继续并更新约束,

🔸对于Descriptions lable扩展UIlable来自所有四方的约束也NumberOflines=0 (⚠️这会给你一个错误去build议,并改变UIlable约束的优先级)

看下面的截图 在这里输入图像说明

改变优先 在这里输入图像说明 比再次更新限制

4.UIViewController代码

  @IBOutlet var tableView: UITableView! var cellIdentifier="cell" var cellXibName = "MyTableCell" override func viewDidLoad() { super.viewDidLoad() tableView.register(UINib(nibName: cellXibName, bundle: nil), forCellReuseIdentifier: cellIdentifier) tableView.rowHeight = UITableViewAutomaticDimension tableView.estimatedRowHeight = 320 } func numberOfSections(in tableView1: UITableView) -> Int { return 3 } func tableView(_ tableView1: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell :MyTableCell = tableView1.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! MyTableCell return cell } 

最后,输出是完美的,你想要的

OUTPUT 在这里输入图像说明

我希望这会对你有用……请让我知道这是否适用于你。

解答:

我是你的问题的存档解决scheme。 希望这可能对你有所帮助

我使用uiview来剪辑所有单元格元素。 在这里输入图像说明

和细胞devise 在这里输入图像说明

代码:

class ViewController:UIViewController {

 @IBOutlet var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() self.tableView.estimatedRowHeight = 100 self.tableView.rowHeight = UITableViewAutomaticDimension self.tableView.register(UINib(nibName: "TestCell", bundle: Bundle.main), forCellReuseIdentifier: "TestCell") // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } extension ViewController : UITableViewDataSource, UITableViewDelegate { func numberOfSections(in tableView: UITableView) -> Int { return 1; } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 10 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as! TestCell cell.selectionStyle = .none return cell } } 

结果: 在这里输入图像说明

细胞高度似乎是问题,对吗? 因为这个约束不能正确地工作。

在使用XIB files时,您需要使用此重写function:

 override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 300 } 

然而,你的约束必须是错的,或者让我们说他们并不完美。 我知道他们正在使用故事板中的原型单元格,但是这并不能使他们100%完美的工作正确吗? 你的UIImageView没有heightwidth 。 你应该尝试设置一些约束。 (或者设置width并使用Aspect Ratio约束)