Search code examples
iosswiftuisegmentedcontroluicontainerviewchildviewcontroller

Calling child view controller using segmented control action?


I have two child view controllers in my parent view controller, I want to call them upon a value change in the segmented control, and want to set the value of the parent imageView through child view controllers.

protocol UserEdittedPhoto {
    func UserIsDone(image:UIImage)
}

class ControllerFinal:UIViewController, UserEdittedPhoto{

    func UserIsDone(imageEditted: UIImage){
        self.usedImage=imageEditted
        self.imageView.image=self.usedImage
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func segmentAction(sender:UISegmentedControl){

        if (segmentedControl.selectedSegmentIndex==0){

            performSegueWithIdentifier("EditIAm", sender: nil)
        }

        else if (segmentedControl.selectedSegmentIndex==1){

            performSegueWithIdentifier("EditIAm", sender: nil)
        }
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if segue.identifier == "EditIAm"{

            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let controller = storyboard.instantiateViewControllerWithIdentifier("ControllerEdit")
            self.presentViewController(controller, animated: true, completion: nil)

            let nextView = segue.destinationViewController as! ControllerEdit
            nextView.originalImage=self.imageView.image!
            nextView.delegate=self
        }

        else if segue.identifier == "FilterIAm"{

            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let controller = storyboard.instantiateViewControllerWithIdentifier("ControllerFilters")
            self.presentViewController(controller, animated: true, completion: nil)

            let nextView = segue.destinationViewController as! ControllerFilters
            nextView.toBeFilter=self.imageView.image!
        }
    }

    class ControllerEdit:UIViewController{
        var delegate: UserEdittedPhoto? = nil
        if (delegate != nil){
        self.originalImage = UIImage(CIImage: CIImage(image: self.originalImage)!.exposureAdjustFilter(sliderValue.value)!)
        self.delegate!.UserIsDone(self.originalImage)
        print("I am Called!")
        }
    }

    class ControllerFilters:UIViewController{
        override func viewDidLoad() {
            print("SAHASHhqdwiuhiuhsaiuhsaiudhiuash")
            controllerFinal?.imageView.image=toBeFilter
            print("SAHASHhqdwiuhiuhsaiuhsaiudhiuash")
            super.viewDidLoad()
        }
}

Solution

  • UPDATE

    To reflect our discussion in the comments below, I don't think you really need Containers and View Controllers to manage your custom controls (Edit / Filters). It's overkill.

    Instead, I think you should be creating custom Views, and then adding them to your main Storyboard.

    Then you could simply hide/show your custom Views when users tap on the Segmented Control as well as passing values to them, for example:

    CustomEditView.valueY = newValueY
    CustomFiltersView.valueX = newValueX
    

    Regarding:

    I need to call it forcefully through segmentedControl action, so that my values in the childView be updated

    Then you need to map the target View Controllers to local variables and use them to update the target View Controller variables when users presses the segments.

    I've update the code and "demo" in my answer to reflect that.
    (Notice that I'm just putting random Strings in the labels to make a point.)

    Now to the complete answer...


    In the setup you described in your other question, which is based on containers, the View Controllers are already there, in the Storyboard. You absolutely don't need to present them again (you can remove performSegueWithIdentifier calls).

    If I understood correctly, you just want to show different "controllers" to the user based on what they choose via a Segmented Control.

    There are some ways for doing that, but the easiest one would be to hide and to show the containers of the ControllerEdit / ControllerFilters View Controllers -- by changing the containers isHidden variable state.

    Like this:

    demo

    Storyboard setup:

    storyboard

    Code (based on my other answer):

    import UIKit
    
    protocol UpdateImageProtocol {
        func userIsDone(image: UIImage)
    }
    
    class ViewController: UIViewController, UpdateImageProtocol {
    
        @IBOutlet weak var imageView: UIImageView!
    
        @IBOutlet weak var changeImageContainer: UIView!
        var controllerEdit: ControllerEdit?
    
        @IBOutlet weak var applyFilterContainer: UIView!
        var controllerFilters: ControllerFilters?
    
        var image = UIImage(named: "hello")
    
        override func viewDidLoad() {
            super.viewDidLoad()
            userIsDone(image: image!)
        }
    
        func userIsDone(image: UIImage) {
            imageView.image = image
        }
    
        override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            if segue.identifier == "controllerEdit" {
                let nextView = segue.destination as! ControllerEdit
                nextView.delegate = self
                controllerEdit = nextView
    
            } else if segue.identifier == "controllerFilters" {
                let nextView = segue.destination as! ControllerFilters
                controllerFilters = nextView
            }
        }
    
        @IBAction func segmentAction(_ sender: UISegmentedControl) {
            if sender.selectedSegmentIndex == 0 {
                changeImageContainer.isHidden = false
                applyFilterContainer.isHidden = true
    
                controllerEdit?.customLabel.text = String(arc4random_uniform(999))
    
            } else {
                changeImageContainer.isHidden = true
                applyFilterContainer.isHidden = false
    
                controllerFilters?.customLabel.text = String(arc4random_uniform(999))
            }
        }
    }
    
    class ControllerEdit: UIViewController {
    
        @IBOutlet weak var customLabel: UILabel!
    
        var image = UIImage(named: "newHello")
        var delegate: UpdateImageProtocol?
    
        @IBAction func changeImage(sender: UIButton) {
            delegate?.userIsDone(image: image!)
        }
    }
    
    class ControllerFilters: UIViewController {
    
        @IBOutlet weak var customLabel: UILabel!
    
        // TODO
    }