radioaktiv
radioaktiv

Reputation: 2539

Passing data to ViewController

I am struggling with the following issue:

I have a ViewController and a separateUIView attached to it which I use instead of storyboard or xib/nib, meaning I took the "drawing views programatically" approach.

class MyViewControllerA: UIViewController {
override func loadView() { 
        self.view = MyViewControllerAView()
    }
}

The above works all fine.

Then within my MyViewControllerAView I am using a third party UI component which loads two UIViewControllers within the MyViewControllerA by using a delegate:

class MachineHomeView: UIView, ThirdPartyUIComponentDelegate {

        //code ...

        func thirdPartyUIComponent(_ thirdPartyUIComponent: ThirdPartyUIComponent, viewControllerAt index: UInt) -> UIViewController {
            switch index {
            case 0:
                return MyViewControllerC()
            case 1:
                return MyViewControllerC()
            //..more code
            }
        }
    }

And the UI looks like:

enter image description here

In a nutshell, I have a ViewControllerA whose View loads two additional ViewControllers - ViewControllerB and ViewControllerC

As you see I am trying to follow the MVC approach by separating the View and the Controller from each other.

The problem I am facing is that I would like pass data from MyViewControllerA to MyViewControllerB and MyViewControllerC.

The first thing that comes up to my mind is to create a property in the MyViewControllerAView e.g callled test. So in viewWillLoad or viewDidLoad I can pass stuff to it like:

self.view.test = "some data"

Then in the delegate where I instantiate the two additonal view controllers I can do:

func thirdPartyUIComponent(_ thirdPartyUIComponent: ThirdPartyUIComponent, viewControllerAt index: UInt) -> UIViewController {
                switch index {
                case 0:
                     let myViewControllerB = MyViewControllerB()
                     myViewControllerB.someProperty = self.test
                    return myViewControllerB
                case 1:
               let myViewControllerC = MyViewControllerC()
                     myViewControllerC.someProperty = self.test
                    return myViewControllerC
                }
            }
        }

In my mind going the above way is breaking the MVC convention because the View is no longer UI responsible only. Therefore I want to avoid that and keep the MVC clean.

Any ideas of how pass data from MyViewControllerA to MyViewControllerB and MyViewControllerC without breaking the MVC pattern or introducing a bad practice ?

Upvotes: 2

Views: 95

Answers (2)

Jacek Głazik
Jacek Głazik

Reputation: 176

UView shouldn't create UIViewControllers and manage them itself. Make ViewControllerA responsible for managing ViewControllerB and ViewControllerC. Great way to do this is make B and C child view controllers of A. You can communicate with parent view controller A by delegate. Apple tutorial how to make this: https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html

However @Milan solution is ok too.

Upvotes: 1

Milan Nosáľ
Milan Nosáľ

Reputation: 19737

I believe you should approach the problem in a following manner.

Move the thirdPartyUIComponent(_:) method out of MyViewControllerAView to the MyViewControllerA - I don't think it's appropriate for the view in MVC to instantiate and handle view controllers. Now the MyViewControllerA view controller would be responsible for view controllers B and C.

Then, since I expect that you need to access the views of B and C in the MyViewControllerAView, pass them directly to the MyViewControllerAView - however, pass only views of B and C, not the view controllers themselves.

This way the A view controller will manage view controllers B and C, but the MyViewControllerAView will still have access to the B.view and C.view to lay them out properly.

P.S.: If the thirdPartyUIComponent(_:) callback should be called when some UI action is triggered by the user on the MyViewControllerAView, then use the delegate pattern to pass that event to the MyViewControllerA to handle it cleanly.

Upvotes: 2

Related Questions