1

I'm trying to make a custom ContainerViewController, but due to lots of difficulties with the ViewController transitions and making everything interactive, I've decided to mimic that functionality myself.

What I basically want to do, is have a paginated UIScrollView (the HeaderView) on the top control different another UIScrollView (the ControllersView) below that contains ViewControllers as pages so that as you swipe to a new page on the HeaderView, it also swipes to the next viewcontroller on the ControllersView. This is what the setup would look like.

My question is, is there anything wrong with having the aforementioned setup? All I'll do to add the view controllers to the ControllersView is just something like: controllersView.addSubview(pagecontroller1.view).

Some posts online seem to say that "the appropriate ViewController functions won't be called" or whatever. What do I seem to be missing here? I'm guessing there's a lot of dismissing and admitting of ViewControllers that I need to call every time a ViewController is out of frame right?

To clarify the question: Is it ok/efficient to do this? Should I be calling some viewWillAppear/disapper functions when the VC's get in and out of frame? If so, what should I call? I'm realizing that if I were to set things up this way, I need to manage a lot of things that are usually handled automatically, but as I mentioned before, custom ContainerViewControllers have failed me and I'm going with this.


PS. If you seem to still be lost on how this will look like, see my previous question here where I originally wanted to use a Container ViewController. There's a much better mockup there.

JoeVictor
  • 1,806
  • 1
  • 17
  • 38
  • I'm sensing a vagueness on good design? Maybe due to confusion between view controllers (`UIViewController` and such subclasses in `UIKit`) and views (`UIView`, which should be the objects/classes/subclasses you put into a `UIScrollView`)? Both have the potential for a hierarchy - that is, you *can* have child views and/or controllers. But a *root* view of a view controller is just that - the root of the hierarchy. Some feel it's "good design" to have this root view have say, six subviews, each with it's own view controller. But only if you are talking threading should you automatically do it. –  Jan 31 '18 at 00:47
  • Conclusion... If you can replace your "Container ViewController" with a "Container View", throwing in a controller for a view inside this container *only* if needed, it's possible. But having two `UIScrollViews` - which manage views, not controllers - manage controllers? Consider replacing one with a navigation controller instead. –  Jan 31 '18 at 00:50
  • I’m sorry I dont think I understand your comment. The reason why I want to use ViewControllers is to compartmentalize the logic of each page. I will have each viewcontroller represent a separate “page” in my apps. (Like for example each viewcontroller might control have things like: search, browse, and settings) and as such, using views seems VERY bloated. – JoeVictor Jan 31 '18 at 00:51
  • I was particularly lost when you mentioned the six subviews part. Basically what I want is a root view controller, yes. With the children not necessarily being added by calling `addChildViewController` as the root ViewController won’t be a Container view controller. Hope this clarifies things :) – JoeVictor Jan 31 '18 at 00:53
  • Okay, so take my "concluding" comment and consider using a toolbar instead of a scroll view. Either one works the same way. A scroll view manages *views* not *view controllers*. A navigation bar or a tool bar manages *view controllers*. Speaking of bloated, would you think a two scroll views with a 3x6 (top x bottom) == 18 views is more bloated than a navigation/tool bar with 6 controllers? (In my world a "navigation bar" controller "navigates" to the "next" controller. A "tool bar" allows the user to select the "tool controller" to use.) –  Jan 31 '18 at 00:53
  • I tried making a custom container view controller as mentioned but that did not work out. I want that specific UI look that I linked to in my previous question From what I understand you are pushing me towards a “stock” container view controller (like a NavigationViewController or custom one, both are not what I am asking for. – JoeVictor Jan 31 '18 at 00:58
  • Not "custom container view controller", "custom container view". And yes, why not use something "stock"? It's what your users are accustomed to! Besides, you can always subclass or extend for the UI look. There's reasons for how UIKit is designed. Those reasons may or may not originate before you were born or worked in app development (I started in 1984 nd some OOP concepts predate that) but they exist for good reason. I'm really not trying to "push" you to anything, just trying to explain certain concepts considered "good design" and how they generally apply to UIKit. Good luck! –  Jan 31 '18 at 02:11
  • It was actually a "custom container view controller" that I attempted to add using a framework developed based off of [this tutorial](https://www.objc.io/issues/12-animations/custom-container-view-controller-transitions/). I understand your preference towards "stock", the thing is, that's not what this question was asking :) Thanks though! – JoeVictor Jan 31 '18 at 02:53

1 Answers1

1

You can add and remove VC In Container Views

For - Is it ok/efficient to do this? Should I be calling some viewWillAppear/disapper functions when the VC's get in and out of frame? If so, what should I call?

As, We need to call WillAppear and Disappear Func when Adding and removing a VC , Thus Try using below Functions That will Handle these Responses

I use the Two specific Functions to add and remove Controller in ContainerView/UIView/SubView in ScrollView inside a UIView

To Add

private func add(asChildViewController viewController: UIViewController)
{
    // Configure Child View
    viewController.view.frame = CGRect(x: 0, y: 0, width: self.firstContainer.frame.size.width, height: self.firstContainer.frame.size.height)

    // Add Child View Controller
    addChildViewController(viewController)
    viewController.view.translatesAutoresizingMaskIntoConstraints = true

    // Add Child View as Subview
    firstContainer.addSubview(viewController.view)

    // Notify Child View Controller
    viewController.didMove(toParentViewController: self)
}

To Remove

private func remove(asChildViewController viewController: UIViewController)
{
    // Notify Child View Controller
    viewController.willMove(toParentViewController: nil)

    secondContainer.willRemoveSubview(viewController.view)

    // Remove Child View From Superview
    viewController.view.removeFromSuperview()

    // Notify Child View Controller
    viewController.removeFromParentViewController()
}

Creating Object

private lazy var FirstObject: firstVC =
  {
    // Instantiate View Controller
    let viewController = self.storyboard?.instantiateViewController(withIdentifier: "firstVC") as! firstVC

    // Add View Controller as Child View Controller
    self.addChildViewController(viewController)
    return viewController
  }()

For - controllersView.addSubview(pagecontroller1.view)

Answer - Yes Approbate func wont be called if pagecontroller1 is not loaded in to memory stack, to load that you need to notify pagecontroller1 that it is going to be added to memory stack as Child View , Just as We initiate a Controller and basically notifies the Controller to get its component loaded to memory stack to get some memory allocations

For Question - Is it fine to nest a UIViewController within another without using addChildViewController?

Check apple Documentation - https://developer.apple.com/documentation/uikit/uiviewcontroller/1621394-addchildviewcontroller

This is necessary just as to notify the controller who is going to be added in Another Parent View as Child

Sample Project

https://github.com/RockinGarg/Container_Views.git

Or

https://github.com/RockinGarg/ContainerView-TabBar.git

If Question is Still not answered Please Tell me what Func Exactly you want to handle by yourself

iOS Geek
  • 4,825
  • 1
  • 9
  • 30