0

I have an app where there is a "DadViewController" which contains a UIScrollView that has paging enabled. Each page is populated with a different UIViewController.

How Do I push a new UIViewController, from a button tap, within one of the controllers contained in the UIScrollView?

class DadView: UIView {

    let model = DadModel()

    let scrollView: UIScrollView = {
        let view = UIScrollView()
        view.isPagingEnabled = true
        // Additional setup...
        return view
    }()



    override init(frame: CGRect) {
        super.init(frame: frame)
        setupScrollView()
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }



    fileprivate func setupScrollView() {
        self.addSubview(scrollView)
        // Autolayout code to pin scrollview to all 4 sides

        let vc1 = VC1()
        scrollView.addSubview(vc1.view)
        vc1.view.frame = CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: SCREEN_HEIGHT)

        // Add additional view controller views with the appropriate frames...

    }
}

class DadController: UIViewController {
    var dadView: DadView!

    override func loadView() {
        super.loadView()
        dadView = DadView()
        view = dadView
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

class VC1: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .green
    }

}
yambo
  • 1,388
  • 1
  • 15
  • 34

1 Answers1

0

Change your DadView setupScrollView to accept a UIViewController instance as argument. And don't call this method in init

class DadView: UIView {

    let model = DadModel()

    let scrollView: UIScrollView = {
        let view = UIScrollView()
        view.isPagingEnabled = true
        // Additional setup...
        return view
    }()



    override init(frame: CGRect) {
        super.init(frame: frame)
//        setupScrollView()
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }



    fileprivate func setupScrollView(_ parentVC: UIViewController) {
        self.addSubview(scrollView)
        // Autolayout code to pin scrollview to all 4 sides

        let vc1 = VC1()
        vc1.view.frame = CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: SCREEN_HEIGHT)
        parentVC.addChild(vc1)
        scrollView.addSubview(vc1.view)
        vc1.didMove(toParent: parentVC)

        // Add additional view controller views with the appropriate frames...

    }
}

In DadViewController after creating DadView instance call setupScrollView method with self

class DadController: UIViewController {
    var dadView: DadView!

    override func loadView() {
        super.loadView()
        dadView = DadView()
        dadView.setupScrollView(self)
        view = dadView
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

Then you can get parent view controller from child viewcontroller and perform push

class VC1: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .green
    }
    @IBAction func buttonAction(_ sender: UIButton) {
        self.parent?.navigationController?.pushViewController(NewVC(), animated: true)
    }
}
RajeshKumar R
  • 15,445
  • 2
  • 38
  • 70
  • Works perfectly! I just needed to change `fileprivate` to `internal` – yambo Apr 09 '19 at 14:56
  • @yambo i think you already get this from the comments the above demo is a matter of transferring code – Shehata Gamal Apr 09 '19 at 15:08
  • @Sh_Khan I'm not sure why you're disliking everything, but this answer is very concise, and answers the question. – yambo Apr 09 '19 at 15:27
  • Because a programmer should get it from even a word no need to list code , Didn't you get that from the comments ? – Shehata Gamal Apr 09 '19 at 15:39
  • @RajeshKumar_R This question is a bit off topic. But now that I can transition to different view controllers from these child controllers, do you know how I Implement my custom view controller transitions? None of the NavigationController delegate functions seem to be getting called on the child controllers when I transition to a new controller. – yambo Apr 10 '19 at 06:49
  • @yambo in your child viewcontroller add self.parent.navigationcontroller.delegate = self – RajeshKumar R Apr 10 '19 at 06:51
  • @RajeshKumarR I figured as much. But when I do `print(self.parent.navigationcontroller)` in the child controllers viewDidLoad, It prints "nil". Do you know the cause of this? – yambo Apr 10 '19 at 07:10
  • @yambo Have you embedded your DadViewController in a navigation controller? – RajeshKumar R Apr 10 '19 at 07:11
  • @RajeshKumarR Yes. In app delegate I have the following `window?.rootViewController = UINavigationController(rootViewController: DadController())` – yambo Apr 10 '19 at 07:14
  • Update: This post cleared everything up https://stackoverflow.com/questions/10982567/why-is-self-navigationcontroller-null-in-viewdidload – yambo Apr 10 '19 at 07:29