使用 UIViewController 作为 TableView 单元格

Posted

技术标签:

【中文标题】使用 UIViewController 作为 TableView 单元格【英文标题】:Use UIViewController as TableView cell 【发布时间】:2016-09-18 20:30:02 【问题描述】:

我有一个在两个 UIViewController 之间切换的分段控件。一个信息视图和一个列表视图 (TableView)。

我想使用第一个 UIViewController 作为我的 TableView 的第一个单元格(即在另一个段上)。

有没有办法将 UIViewController 转换为单元格或以某种方式将其用作 TableView 的单元格?

【问题讨论】:

是的,您可以将 VC 的视图添加为单元格 contentView 的子视图。您还需要将 VC 作为子 VC 添加到某些父 VC。使用自动布局定位 VCs 视图。 谢谢。如何将我的 InfoViewController 添加为孩子?对于什么父母。这部分我做得不太好。 【参考方案1】:

以您自己的方式使用此代码。在这里,我们将控制器视图添加为单元格的子视图,并使用自动布局来正确管理。您只需要理解使用代码即可。

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath:indexPath)
    cell.layoutIfNeeded()

    let infoVC = self.storyboard.instantiateViewControllerWithIdentifier("InfoVC")
    self.addChildViewController(infoVC)
    cell.contentView.addSubview(infoVC.view)

    infoVC.view.translatesAutoresizingMaskIntoConstraints = false
    cell.contentView.addConstraint(NSLayoutConstraint(item: infoVC.view, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: cell.contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0.0))
    cell.contentView.addConstraint(NSLayoutConstraint(item: infoVC.view, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: cell.contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0.0))
    cell.contentView.addConstraint(NSLayoutConstraint(item: infoVC.view, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: cell.contentView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0.0))
    cell.contentView.addConstraint(NSLayoutConstraint(item: infoVC.view, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: cell.contentView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0.0))

    infoVC.didMoveToParentViewController(self)
    infoVC.view.layoutIfNeeded()

【讨论】:

这段代码假设拥有UITableView的VC是DataSource 我刚刚回答了您对@Sajjon 的建议,因为通过阅读提问者想要做什么,我也有同样的想法。如有错误,您可以更正答案。 这似乎有效。但是我会尝试。让我问你一件事。我的 tableview 的其他单元格具有不同大小的 infoVC。我该如何处理?例如...我的 InfoVC 的高度为 300,而我的其他单元格的高度为 70。 您可能需要考虑添加一些代码来解决重复使用单元格的情况。在添加新视图控制器之前,应删除以前的视图控制器。完成后,之前的 VC 应该调用 willMove(toParentViewController: nil)removeFromParentViewController() UITableViewCell 有一个方法 prepareForReuse() 在重用单元格之前调用。覆盖此方法并在其中包含的任何 UIViewController 上调用 removeFromParentViewController() 是一个可行的选择。【参考方案2】:

Swift 5.0 语法

let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for:indexPath)
cell.layoutIfNeeded()

let storyboard = UIStoryboard(name: "StoryboardName", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ViewControllerNameHere")

self.addChild(vc)
cell.contentView.addSubview(vc.view)

vc.view.translatesAutoresizingMaskIntoConstraints = false
cell.contentView.addConstraint(NSLayoutConstraint(item: vc.view, attribute: NSLayoutConstraint.Attribute.leading, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cell.contentView, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1.0, constant: 0.0))
cell.contentView.addConstraint(NSLayoutConstraint(item: vc.view, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cell.contentView, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1.0, constant: 0.0))
cell.contentView.addConstraint(NSLayoutConstraint(item: vc.view, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cell.contentView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: 0.0))
cell.contentView.addConstraint(NSLayoutConstraint(item: vc.view, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cell.contentView, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1.0, constant: 0.0)) 

vc.didMove(toParent: self)
vc.view.layoutIfNeeded()

return cell

【讨论】:

在这种情况下,在视图控制器“vc”中,您将如何访问单元格属性?【参考方案3】:

好吧,我建议使用自己的 nib 文件创建一个自定义 UITableViewCell 并从 nib 加载它。

这可以添加/取消队列到UITableViewSection。 然后可以在 UI Builder 中以您希望的任何方式设计 Cell 本身。您可以将所有内容放入您喜欢的单元格中。

这里有一个简短的教程如何做到这一点: using-nib-xib-files

可以在此处找到有关该主题的问题: Custom UITableViewCell from nib in Swift

【讨论】:

我可以这样工作。问题是我已经有了故事板中所有约束的布局。有办法将其“转换”为 nib(或 xib)文件吗? 很抱歉告诉你,但我认为没有自动的方法可以这样做。我认为您可以将内容复制到 nib/xib 文件中。我认为创建这样的自定义单元格将是一个干净的解决方案。此外,它易于维护,您不必在代码中设置约束。您可以尝试使用ContainerViewController 将另一个故事板加载到 xib/nib 单元格中。 (这肯定是一个肮脏的黑客,它不会推荐它!)developer.apple.com/library/content/featuredarticles/…

以上是关于使用 UIViewController 作为 TableView 单元格的主要内容,如果未能解决你的问题,请参考以下文章

在不使用 IB 的情况下添加 UIImageView 作为 UIViewController 的子视图

从 UIViewController 显示 UIView 作为上下文菜单预览

在 uiviewcontroller 中添加 uitableviewcontroller 作为子视图时出错

如何将 UIViewController 作为子视图添加到 UIViewController(RootViewController)?

添加根视图控制器 OCMockObject[UIViewController] 作为子视图控制器错误

如何最好地将使用一个 UIViewController 将所有页面作为 UIView 处理为 StoryBoarding 和 UIPageView 的图书应用程序转换?