2
votes

I currently have a base view controller say AVC which present another view controller say BVC over current context like this:

let bvc: BVC = sb.instantiateViewControllerWithIdentifier("BVC") as! BVC
bvc.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
self.presentViewController(bvc, animated: true, completion: nil)

Then I am setting a value in BVC and on dismiss, am using the same value to perform a function in the viewWillAppear of AVC. However, I noticed that when presenting OverCurrentContext, on dismiss, the viewWillAppear does not called.

How do I go about fixing this? I need a semi-transparent presented view and hence would need to use OverCurrentContext.

Thanks!

2

2 Answers

7
votes

bhalla,

Two ways,

Way 1

You can make use of delegates and protocol for this :)

Declare a protocol in BVC and confirm it in AVC. And when you are done in BVC call the method of protocol and let the AVC dismiss BVC and by doing that you can pass the data from BVC to AVC as well.

Example :

Declare a protocol like the one below in BVC

protocol letsCallParent{
    func amDoneHere(dataIwantToPass : String)
}

Declare a property to hold the reference of view controller confirming to this protocol in BVC

var myParent : letsCallParent?

And when you are done with BVC and you have to dismiss youself call the method in delegate and pass the data you want to pass :) Now it would be good coding practice to expect the parent (AVC) to dismiss BVC rather then call dismissViewController on self :)

if let parent = myParent {
    parent.amDoneHere("Hi am Done here")
}

In AVC confirm to the protocol using

class AVC: UIViewController,letsCallParent{

and after instantiating BVC before presenting it assign the self as myParent of BVC :)

let bvc: BVC = sb.instantiateViewControllerWithIdentifier("BVC") as! BVC
bvc.myParent = self

and finally implement the protocol method :)

func amDoneHere(dataIwantToPass: String) {
   print("\(dataIwantToPass)")
   //if you want to dismiss BVC call 
   //if you have pushed bvc
   //self.navigationController?.popToViewController(self, animated: true)
   //if you have presented
   //self.dismissViewControllerAnimated(true, completion: nil)
}

WAY 2

Make use of unwind segue :) making use of unwind segue will eliminate the need to write delegate and protocols and all :) also provides the parent view controller an opportunity to access the child view controller as well :) Once you have an access to child VC which is BVC you can read the data from it :)

Example :

Declare an unwind segue :) If you want BVC to call a metod of AVC when it gets dimissed, declare a unwind segue method in AVC :)

@IBAction func cancelChildVC(segue:UIStoryboardSegue) {
        let childVC : SecondViewController = segue.sourceViewController as! SecondViewController
        print(childVC.name)
        self.dismissViewControllerAnimated(true, completion: nil)
}

The signature of the method is fixed :) It has to be a @IBAction and it has to accept segue as paramter :)

Only after declaring this method :) go to your story board and select the BVC and hold control and drag from the button or any other view you have in BVC to dismiss it, to Exit option in BVC :)

Have look at gif provided below for clear understanding :)

enter image description here

If you do it correctly you will see the method that you have declared in AVC coming up as pop up option :) select it :) Thats it :) Whenever you tap on the button or the view from which you have dragged the control to Exit, the method in your AVC gets called :)

In AVC's method you can access the BVC instance because now you have the access to segue instance :) remember prepareForSegue method for direct segues, this is similar to that for unwind segue :)

let childVC : SecondViewController = segue.sourceViewController as! SecondViewController
print(childVC.name)
self.dismissViewControllerAnimated(true, completion: nil) 

Notice the usage of "segue.sourceViewController" once you have the acces to BVC access its data :)

Hope my answer helped :)

2
votes

Issue Explanation

As u noticed that when presenting OverCurrentContext, viewWillAppear will not be called on dismiss.

Why ?

viewWillAppear will be called whenever u back to your view (in case that the view is already disappeared). When u present a new view using OverCurrentContext, the main view is still appeared and u present a new one over it or over part of it ! Popup effect !

Because of this logic, viewWillAppear will not be called when u dismiss the OverCurrentContext view and u have to handle it manually using any way like @Sandeep did above.