How do I pass values from a VC back to the VC that presented it?
by
Lou Franco
Filed under: iOS
Ok, so you have a view controller that brings up another view controller. Let’s call the first one FirstVC
and the second one SecondVC
. FirstVC
either presents SecondVC
or there is some segue that it uses to bring it up.
Anyway, while the user is looking at SecondVC
, FirstVC
is still there. On an iPad, you might even be able to see it if the second VC is a popup. Something you are doing in SecondVC
might need to change something in FirstVC
while it’s still up or just before it dismisses.
For example, FirstVC
might be a menu and SecondVC
is a settings popup for one of the menu items. Depending on what you do on the settings popup, the menu might need to change. How does it know how to do this?
The very standard way to do this in iOS is with a delegate, but if you are in Swift and you have just one simple thing, here’s a quicker way—use a closure instead.
The delegate is a much better choice if you have a bunch of different things that you may want to communicate, like UITableViewDelegate
, and you might refactor to that later if you keep adding closures.
Here’s how you do it.
In SecondVC
, add a closure property like this:
public var didUpdate: (() -> ())?
In SecondVC
, when you want to communicate that you updated, call didUpdate
:
self.didUpdate?()
Then, in FirstVC
, you need to set the didUpdate
property before you present it, for example:
let vc2 = SecondVC() // or instantiate it from a storyboard or whatever
vc2.didUpdate = {
// do whatever you need to do when the update happens
}
// present vc2
If you are using a segue, you can set didUpdate
in the prepare for segue function.
BONUS: Pass a variable on update
If you need to pass a variable back to FirstVC
, then declare didUpdate
like this:
public var didUpdate: ((String) -> ())?
and call it like this:
self.didUpdate?("Hello")
and set it up like this
vc2.didUpdate = { s in
// do whatever you need to do when the update happens
// s has the string you passed
}