除非我添加另一个 UIView,否则 ScrollView 中的 TableView 为空?

Posted

技术标签:

【中文标题】除非我添加另一个 UIView,否则 ScrollView 中的 TableView 为空?【英文标题】:TableView empty inside ScrollView unless I add another UIView? 【发布时间】:2018-10-03 07:50:23 【问题描述】:

我有一个 ViewController,里面有一个 ScrollView(固定到边缘,4 个约束)。一切都很好。

然后,我将 TableViewController 作为 ChildViewController 添加到 ScrollView。 TableViewController 被硬编码为 3 行。 TableViewController 的视图被固定到完整的 ScrollView。

@IBOutlet weak var SV: UIScrollView!

override func viewDidLoad()

    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let TVC        = storyboard.instantiateViewController(withIdentifier: "TVC") as! TVC

    addChildViewController(TVC)
    SV.addSubview(TVC.view)
    TVC.didMove(toParentViewController: self)

    TVC.view.translatesAutoresizingMaskIntoConstraints = false
    TVC.view.topAnchor.constraint(equalTo: SV.topAnchor).isActive = true
    TVC.view.leadingAnchor.constraint(equalTo: SV.leadingAnchor, constant: 100).isActive = true
    TVC.view.trailingAnchor.constraint(equalTo: SV.trailingAnchor, constant: -100).isActive = true
    TVC.view.bottomAnchor.constraint(equalTo: SV.bottomAnchor).isActive = true

如果我打开调试器,我会发现 ScrollView 布局不明确,并且永远不会为表视图控制器调用 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell(为什么?)。

相反,如果我只是在情节提要或任何其他视图、滚动视图内添加一个标签,并向其添加 4 个约束,则将显示 TableView 并按预期调用 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

这是怎么回事? ScrollView 不应该模棱两可,因为 TableView 应该计算它自己的内在内容大小?如果它单独在 ScrollView 中,它永远不会填充自己的 tableview 有什么问题?

我正在添加整个示例项目。如果你运行它,结果是预期的,tableview 会显示出来。如果您转到情节提要并从 ScrollView 中删除标签,则根本不会填充 TableView。

这里不知道怎么直接添加sampleproject,所以上传了。只需运行它,然后从情节提要中删除唯一的标签并重新运行它,不再有表格视图。 https://wetransfer.com/downloads/e0a75a995992cdc2be9120224515549920181003074547/1083bc9a3cb34fe9b1ab8e513b1520f020181003074547/e68826

PS:忽略其他东西,比如那里的子视图控制器。我唯一的问题是为什么当标签存在于同一个 ScrollView 中时显示 tableview 而当标签被删除时不显示。

【问题讨论】:

【参考方案1】:

首先,应用于 ScrollView 中的视图的约束有点特殊。它们没有链接到 ScrollView 的框架,它们有点链接到 ScrollView 的“contentSize”。通常,如果您在另一个视图中有一个视图,并且内部视图在所有方向上都固定在超级视图上,它要么会拉伸以匹配父级大小(如果父级约束被很好地定义为不同的父级),或者如果父约束未相对于另一个父定义定义,则父将“包装”子大小。

现在 ScrollView 在这种情况下的行为有点不同,ScrollView 的大小永远不会“包裹”孩子。添加子约束只是为了告诉 ScrollView,滚动区域是什么(contentSize)。

此外,在您的情况下,您可以将 UITableView 视为“特殊”ScrollView,无法为 ScrollView 提供足够的信息来计算可滚动内容。如果你在各个方向固定 tableView,它只会告诉 TableView,“与所有方向的父对齐”,但滚动视图不会知道“我可以滚动多少”。

因此,由于上述问题,您通常会在 ScrollView 内添加一个 UIView 以充当“容器”,并根据 scrollDirection,将视图宽度/高度设置为等于 ScrollView 或与滚动视图(再次取决于用例)。然后,您希望在滚动视图中添加的所有内容都添加到 UIView 中。内容也以这种方式固定,它不允许“压缩”强制父视图(又名容器)拉伸以“包装”整个内容,这样,滚动就会知道滚动有多少地区。

ScrollView 不应该模棱两可,因为 TableView 应该计算它自己的内在内容大小?

这是错误的,内在内容大小,定义了视图绘制所需的最小大小。现在想一想,一个tableView需要多少空间才能被绘制出来,如果没有添加其他特殊实现,答案是0。tableView的宽/高可以为0,没有任何约束可以防止这种情况。

现在总结一下,您的实现有点错误,要修复它,我建议仔细查看显示如何使用自动布局实现 UIScrollView 的众多教程之一。 您会看到大多数实现将:

在 UIScrollView(又名“containerView)”内添加一个 UIView 然后视图将在各个方向固定到 UIScrollView 那么容器的宽度或高度将被设置为等于滚动视图或滚动视图的父级 然后内容将被添加到“containerView”中 然后将对内容应用约束,使容器必须环绕内容。

【讨论】:

是的,我只是一个 ios 开发新手,想弄清楚一些事情。非常感谢您的解释,现在为什么会发生这种情况确实很有意义。我将尝试重新制作我上传的项目,我现在可能会通过你的解释成功。非常感谢你。看来我现在必须完成工作:D 祝你好运,编码愉快 ;) 只有一个问题仍然存在......为什么表格视图甚至不尝试填充自己?我现在知道视图是错误的,还有约束......但这不应该影响 tableview 功能吗? 为了填充tableView,您需要两个满足两个条件:正确设置tableView的数据源(您这样做),并且表格视图的高度必须> 0,这取决于您的auto问题-你没有完成的布局

以上是关于除非我添加另一个 UIView,否则 ScrollView 中的 TableView 为空?的主要内容,如果未能解决你的问题,请参考以下文章

除非滚动表格,否则 UITableViewCell 内的 UIView 调整大小不显示

除非另一个 div 存在,否则让 div 占据页面的 100%

除非当前场景中存在所有数据,否则如何防止转到另一个 Storyboard 场景?

除非收到另一条消息,否则 Websocket 客户端在握手后无法发送

除非我添加溢出,否则 CSS 背景颜色不会显示:隐藏?为啥?

标签的自动布局水平对齐,除非另一个项目侵占