问题
在您的问题标题中,您询问了如何解决“Swift TableViewCell xib 没有约束”的问题。此外,在赏金中,您指定答案应该是:
一个充分的答案,说明为什么在移动到
xib,当它们存在于 xib 中时,以及如何解决这个问题。
据我了解,您的问题分为两部分:
- 自定义 TableViewCell xib 没有约束的问题
- 为什么从 Storyboard 原型复制/粘贴到 xib 时会丢失约束
对于问题 #1,我使用了与您在自定义单元格 xib 中的屏幕截图中显示的几乎所有相同的约束,并且它有效。我将在下面更详细地解释。
对于问题 #2,我发现约束并没有丢失。您可能需要共享您的项目,以便其他人可以复制您遇到的问题。我将具有类似约束的 Storyboard 原型单元复制/粘贴到 xib 上,但约束没有任何问题。所以我可以确认复制/粘贴功能确实有效。
解决方案演示
我创建了以下演示来测试您的问题。请参阅下面的屏幕截图。 tableView 包含六个单元格。第一个和第二个是相同的并且具有重用标识符MyCell。第 3 和第 4 是相同的并且具有重用标识符MyCopyPasteCell。第 5 和第 6 是相同的并且具有重用标识符MyPrototypeCell。
MyCell 存在于 xib 中,并使用几乎与屏幕截图中显示的所有相同约束。如您所见,没有约束问题。 MyCopyPasteCell 使用类似的约束,并从 Storyboard 原型复制/粘贴到 xib。 MyPrototypeCell 是复制的原始原型。即使原型被复制到 xib,最后四个单元格看起来完全相同。约束从原型转移到 xib 没有问题。
约束
在下面的代码中,我列出了您在屏幕截图中为 ContentView 显示的所有约束。 (请注意,我还实现了height=20、aspect=1:1 和height=75 约束,尽管它们没有在下面列出。)两个约束被注释掉了,因为我没有使用它们。我还添加了一个约束来替换另一个未使用的约束。
// 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。这也与您的 Storyboard 中的原型单元格(用于工作) 屏幕截图完全不匹配。我用bottomMargin = Profile Image.bottom + 17替换了它,它只是用17替换了188.5。
第二个注释约束// Username Label.top = topMargin + 20(将用户名和topMargin 分开20)在技术上可以工作。但是,它的功能对于 Profile Image.top = topMargin + 20(将 Profile Image 和 topMargin 分隔 20)和 Profile Image View.top = Username Label.top(将 Profile Image 和 Username 设置为相同的顶部分隔,即 20)是多余的。
MyTableViewController
以下是我的视图控制器。基本上我创建了三个部分,每个部分有两个单元格/行。 MyCell 和 MyCopyPasteTableViewCell 来自 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