将子视图控制器的视图添加到动态UITableViewCell中

9

如何将子视图控制器的视图添加到自定义的 UITableViewCell 中?在 cellForRowAtIndexPath 中可以像下面这样添加视图:

self.addChildViewController(controlsViewController)
cell!.cellView.addSubview(controlsViewController.view)
controlsViewController.didMoveToParentViewController(self)

但是当单元格消失时,我需要删除此子视图控制器。我不太确定如何做到这一点。有更好的方法吗?


如何将子视图控制器的视图添加到自定义UITableViewCell中? 不要这样做,这不是使用子视图控制器的好方法。在这种情况下,只需添加视图并忘记关于视图控制器的事情。 - matt
那似乎很有道理。我一直在尝试将所有内容转换为使用MVC,但这部分正在成为噩梦!如果您将您的评论发布为答案,我会将其标记为正确! - Tometoyou
2个回答

9
通过委托来完成。我已经在集合视图上这样做了,你也可以在表格视图上这样做。按照以下步骤操作:
1. 在你的自定义单元格类中创建一个delegateHandler并覆盖你的awakeFromNib()方法。例如:
protocol BibleReadingSliderProtocol: class {
    func addThisViewControllerAsChild(audioViewController :AudioViewController)
}

class BibleReadingSliderCollectionCell: UICollectionViewCell {

    @IBOutlet weak var containerView: UIView!

    var audioVC = AudioViewController()
    weak var bibleReadingSliderDelegate:BibleReadingSliderProtocol?

    override func awakeFromNib() {
        super.awakeFromNib()

        print("Awake call from cell")
        // Initialization code

         let storyboard = UIStoryboard(name: "Main", bundle: nil)
        audioVC  = storyboard.instantiateViewController(withIdentifier: "AudioViewController") as! AudioViewController
        audioVC.view.frame = self.containerView.bounds
        self.containerView.addSubview(audioVC.view)

        if self.bibleReadingSliderDelegate != nil {
            self.bibleReadingSliderDelegate?.addThisViewControllerAsChild(audioViewController: audioVC)
        }

    }
}
  1. In your ViewController where you are using this custome cell (either tableview or collection view) define the delegate hander

    func addThisViewControllerAsChild(audioViewController: AudioViewController) {
        self.addChildViewController(audioViewController);
     }
    
不要忘记在 cellForItemAt/cellForRowAt 方法中将您的委托设置为此视图控制器。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let imageSliderCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! BibleReadingSliderCollectionCell

    imageSliderCollectionViewCell.bibleReadingSliderDelegate = self
    return imageSliderCollectionViewCell
}

但是 awakeFromNibcellForItemAt 之前被调用。 - Josh Bernfeld
1
我认为他的意思是要重写layoutSubviews方法。@JoshBernfeld - aclima

3
不要误解MVC。并不是世界上每个视图都需要有自己的独立视图控制器!主视图有一个视图控制器,但在主视图中的按钮并没有自己的视图控制器;它只是与主视图的视图控制器交流。
这个视图也是如此。视图可以非常容易地出现和消失;当您不需要时,请不要添加额外的视图控制器的沉重负担!只需抓住视图(以某种方式)并将其放入单元格的contentView中或从单元格的contentView中移除,在cellForRowAtIndexPath:方法中,就像处理任何其他视图一样 - 但使用您的表视图控制器或表视图数据源/委托或者是负责的对象来管理。不要仅仅因为这个小视图而添加额外的视图控制器,那可能会是视图控制器的不良使用。

2
我尝试让这个程序有一个视图控制器的唯一原因是因为它与一些额外的逻辑相关,当该视图中的按钮被按下时,那个覆盖视图应该与服务器通信。我想我可以从视图中与服务器类进行通信,但这似乎有点不对。 - Tometoyou
我完全理解并猜测到这可能是情况,但是除了使用额外的视图控制器之外,还有其他封装该特殊逻辑的模式。 - matt
你推荐哪些设计模式?目前与服务器通信的代码是单例的,我从视图中的按钮按下调用单例中的函数。 - Tometoyou
如果这个视图只在一个表视图中出现,那么它完全可以由管理表视图的同一视图控制器来管理。如果感觉不好,那么表视图的视图控制器可能会有某种辅助对象,在将此视图插入接口时指向该对象进行管理。 - matt
正确的模式是使用委托回调到视图控制器,然后与服务器通信并适当地更新单元格。 - DBoyer
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接