Adding Child View Controller view to dynamic UITableViewCell
Asked Answered
L

2

9

How can I add a view of a child view controller to a custom UITableViewCell? I can add the view like this inside cellForRowAtIndexPath:

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

But when the cell disappears, I need to remove this child view controller. I'm not really sure how to do that. Is there a better way to go about this?

Labyrinthodont answered 12/6, 2015 at 22:13 Comment(2)
"How can I add a view of a child view controller to a custom UITableViewCell?" Don't. This is not a good use of a child view controller. Just add a view and forget about view controllers in this situation.Hermia
That seems to make sense. I've been trying to convert everything to use MVC but this part is being a nightmare! If you post your comment as an answer I'll mark it correct!Labyrinthodont
H
3

Don't misunderstand MVC. Not every view in the world needs to have its own personal view controller! A main view has a view controller, but a button in that main view does not have its own personal view controller; it simply talks to the main view's view controller.

The same is true of this view. Views can come and go very easily; do not add the heavyweight burden of an additional view controller when you don't need to! Just grab the view (somehow) and stick it into the cell's contentView or remove it from the cell's contentView in cellForRowAtIndexPath:, just like any other view - but manage it using your table view controller or table view data source / delegate or whatever is in charge here. Don't add an extra view controller to the story just for the sake of this one little view. That's likely to be a bad use of view controllers.

Hermia answered 12/6, 2015 at 22:23 Comment(7)
The only reason I was trying to make this have a view controller was because there's some extra logic associated with it where that overlaid view should communicate to a server when a button in that view is pressed. I guess I can communicate to the server class from the view but it seems a bit wrong.Labyrinthodont
I understand perfectly and I guessed that this might be the case, but there are other patterns for encapsulating that special logic than using an extra view controller.Hermia
What patterns do you recommend? At the moment the code that communicates with the server is a singleton and I call a function in the singleton from a button press in the view.Labyrinthodont
Well, if the only place where this view ever appears is in this one table view, then it can perfectly well be managed by the same view controller that manages the table view. If that feels horrible, then the table's view controller might have some sort of helper object to which you point this view's management when you insert it into the interface.Hermia
The proper pattern is to use a delegate to callback to the view controller which then communicates with the server and updates the cell appropriately.Saragossa
@DBoyer, you can't say that's the "proper pattern". You could easily add an extension to UIView to traverse the Response chain in order to find the first responder VC in the hierarchy. You could also set a weak variable to hold a reference, use segues with static cells. There are quite a few ways to approach this. Some apps have insane complexity and require dynamism that invalidates there being one 'right' way.Meridithmeriel
I was referring this khanlou.com/2015/04/view-controllers-in-cells to implement some sort of appstore ui with multiple types collection views under tableview. Until now it was fine but cell doesn't resize properly in case of self sizing if you are using some container cell and keep changing the controller's view with different height on reused cellSnobbery
T
9

Do it via delegation. I have done on collection view ,you can do it on tableview too. follow the below steps

1 .In your custom cell class create a delegateHandler and override your awakeFromNib() method. eg

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);
     }
    

And Dont forget to set your delegate to this viewcontroller in 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
}
Troopship answered 7/11, 2016 at 10:48 Comment(2)
But awakeFromNib is called before cellForItemAtCroquet
i think he meant to override layoutSubviews @JoshBernfeldUrn
H
3

Don't misunderstand MVC. Not every view in the world needs to have its own personal view controller! A main view has a view controller, but a button in that main view does not have its own personal view controller; it simply talks to the main view's view controller.

The same is true of this view. Views can come and go very easily; do not add the heavyweight burden of an additional view controller when you don't need to! Just grab the view (somehow) and stick it into the cell's contentView or remove it from the cell's contentView in cellForRowAtIndexPath:, just like any other view - but manage it using your table view controller or table view data source / delegate or whatever is in charge here. Don't add an extra view controller to the story just for the sake of this one little view. That's likely to be a bad use of view controllers.

Hermia answered 12/6, 2015 at 22:23 Comment(7)
The only reason I was trying to make this have a view controller was because there's some extra logic associated with it where that overlaid view should communicate to a server when a button in that view is pressed. I guess I can communicate to the server class from the view but it seems a bit wrong.Labyrinthodont
I understand perfectly and I guessed that this might be the case, but there are other patterns for encapsulating that special logic than using an extra view controller.Hermia
What patterns do you recommend? At the moment the code that communicates with the server is a singleton and I call a function in the singleton from a button press in the view.Labyrinthodont
Well, if the only place where this view ever appears is in this one table view, then it can perfectly well be managed by the same view controller that manages the table view. If that feels horrible, then the table's view controller might have some sort of helper object to which you point this view's management when you insert it into the interface.Hermia
The proper pattern is to use a delegate to callback to the view controller which then communicates with the server and updates the cell appropriately.Saragossa
@DBoyer, you can't say that's the "proper pattern". You could easily add an extension to UIView to traverse the Response chain in order to find the first responder VC in the hierarchy. You could also set a weak variable to hold a reference, use segues with static cells. There are quite a few ways to approach this. Some apps have insane complexity and require dynamism that invalidates there being one 'right' way.Meridithmeriel
I was referring this khanlou.com/2015/04/view-controllers-in-cells to implement some sort of appstore ui with multiple types collection views under tableview. Until now it was fine but cell doesn't resize properly in case of self sizing if you are using some container cell and keep changing the controller's view with different height on reused cellSnobbery

© 2022 - 2024 — McMap. All rights reserved.