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

时间:2018-10-03 07:50:24

标签: ios swift uitableview uiscrollview

我有一个内部带有ScrollView的ViewController(固定到边缘,有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应该计算其自身的固有内容大小? tableview有什么问题,如果单独在ScrollView中,它将永远不会填充自身?

我要添加整个示例项目。如果运行它,则预期结果,将显示表视图。如果您转到情节提要并从ScrollView中删除标签,则将根本不会填充TableView。

我不知道如何直接在此处添加sampleproject,因此我将其上传。只需运行它,然后从情节提要中删除唯一的标签,然后重新运行即可,不再有表格视图。 https://wetransfer.com/downloads/e0a75a995992cdc2be9120224515549920181003074547/1083bc9a3cb34fe9b1ab8e513b1520f020181003074547/e68826

PS:忽略其他内容,例如其中的子视图控件。我唯一的问题是,为什么当标签存在于同一ScrollView中时显示表格视图,而在删除标签时却不显示表格视图。

1 个答案:

答案 0 :(得分:0)

首先,应用于ScrollView内的视图的约束有点特殊,可以说。它们没有链接到ScrollView的框架,而是链接到ScrollView的“ contentSize”。通常,如果您在另一个视图内部有一个View,并且该内部视图在所有方向上都固定在superView上,则它会拉伸以匹配父级大小(如果父级约束已很好地定义给其他父级),或者如果未相对于另一个父级定义父级约束,则父级将“包装”子级大小。

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

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

因此,由于上述问题,通常在ScrollView内添加一个UIView充当“容器”,然后根据scrollDirection将视图的宽度/高度设置为等于ScrollView或父视图的父级。 scrollView(再次取决于用例)。然后,将要包含在scrollView中的所有内容添加到UIView中。内容也以这种方式固定,即不允许“压缩”强制父视图(又称容器)拉伸以“包装”整个内容,这样,滚动条将知道滚动条的数量区域。

  

ScrollView不应模棱两可,因为TableView应该计算其自身的固有内容大小?

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

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

  • 在UIScrollView(又称为“ containerView”)中添加一个UIView
  • 然后将视图全方位固定到UIScrollView
  • 然后将容器的宽度或高度设置为等于scrollView或滚动视图的父级
  • 然后将内容添加到“ containerView”中
  • 然后将约束应用于内容,以使容器必须包裹内容。