Know recent performed/popped segue? - ios

Am I able to know which segue has just been performed/popped?
For example I have 2 controllers:
View Controller A: Have 1 button that navigates to View B.
View Controller B: Have back button to View A.
I want in View A can detect that the View B just been popped out from stack, so I can do something in ViewWillAppear.
Can I do it?

You can name the segue and then implement prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) method, where you check the identifier if the segue. If it's the segue from ControllerA to ControllerB, just setup some flag that you will check in the viewWillAppear method.
Something like this:
var pushedB = false
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "mySegueName" {
pushedB = true
}
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if pushedB {
pushedB = false
// TODO your action
}
}

Related

prepare segue - destination View Controller is called twice

In Xcode 13.1 I programmed the following code into my source view controller. It's working so well that it's calling the destination view controller twice (instead of once).
This is my code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToNextViewControllerSegue" {
let destVC = segue.destination as! DestinationViewController
destVC.categoryTag = tag
}
}
Any idea what I'm doing wrong?
Let me include the IBAction code as well (This doesn't seem to be the problem, though.)
#IBAction func startButtonTapped(_ sender: UIButton) {
if tag == 1 || tag == 2 {
self.performSegue(withIdentifier: "goToNextViewControllerSegue", sender: nil)
} else {
createAlert()
}
}
Thanks for any help!
Add a breakpoint to prepare(for segue: sender:) and look at the backtrace to see where it is being called from. My guess is that you have connected the button to the segue in the storyboard, and then also to the action method mentioned in your question, so the segue is being performed twice.

View controller with 2 destinations

I have 2 buttons in a view controller. If button 1 is clicked, then go to WebView controller. If button 2 is clicked then go to ArtView controller.
How to make override func prepare(for segue: UIStoryboardSegue, sender: Any?) have 2 destinations depending on the button clicked?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? WebViewController {
// your code
}
if let destination = segue.destination as? ArtViewController {
// your code
}
}
Hope it will help! :)
Have each button invoke a different segue, either by control-dragging segues directly from the button, or by calling performSegue(withIdentifier:sender:) from your buttons' IBAction code.
Then use code in prepare(for:sender:) to figure out which destination is being invoked.
You can:
Check the identifier on the segue (not recommended - fragile)
Check the class of the destination view controller (better than 1)
Have each view controller implement a protocol and check the protocol of the destination:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.destination {
case let webView as WebViewProtocol:
//Your code for a web view
case let artView as ArtViewProtocol:
//Your code for an Art View
}
}
Option 3 is reliable while providing loose coupling (each case can trigger any view controller that conforms to the desired protocol. All it needs to know is that the destination understands the desired protocol.)

Programmatic embed segue

I'm using a Page View Controller to implement an image carousel in my app. I have a container view in my parent view controller which has an embed segue to the Page View Controller. The problem I'm having is when I need to go off and fetch these images asynchronously and the segue happens before viewDidLoad gets the images.
My prepare for segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "startCarousel" {
let carouselPageViewController = segue.destination as! CarouselPageViewController
carouselPageViewController.images = carouselImages
}
}
in viewDidLoad:
GalleryManager.sharedInstance.getData = {
(data) in
// Assign images to instance property here ...
}
My thinking is that once I get the images that I programmatically start the segue myself. Or if I should be doing this a different way any advice would be much appreciated.
You can do something like, return false in shouldPerformSegue and initiate segue when data is loaded
i.e.
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if identifier == "startCarousel" {
return (detail != nil)
}
return true
}
Then in viewDidLoad
GalleryManager.sharedInstance.getData = { [weak self]
(data) in
self?.performSegue(withIdentifier: "startCarousel", sender: nil)
}
No, you can't delay an embed segue. If you use an embed segue it fires as soon as the view controller is loaded.
You need to wait until the data loads and then call the setViewControllers(direction:animated:completion) to install the view controllers that you will use to display the data once the data is loaded.
Swift 3, Xcode 8
You can realize in this way:
set a reference to your page view controller in prepareForSegue in your masterViewController:
var myContainerViewController: UIPageViewController?
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "embedSegue" {
if let destination = segue.destination as? YourPageViewControllerClass {
self.myContainerViewController = destination
}
}
Define a function in your own pageViewController class:
func someFunction(){
//configure your image or swipe page
}
when you get the images, in your masterViewController call:
self.myContainerViewController?.someFunction()
you can't delay an embed segue.
you try to put button in view controller and then after view load set button click to set image...

How to specify which view controller you are preparing for with Swift's prepareForSegue function?

So I have multiple buttons on one view segue'ing to other views. I have the function prepareForSegue() at the bottom of my code preparing one segue, however the app crashes when I use another segue on the view, even if it doesn't need any preparing.I think that the problem is that all of the segues use the prepareForSegue() function, however the storyboard ID is different than the view it is transitioning to.Is there any way to specify a prepareForSegue() function for each separate segue on the same view?Code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let theVC: ViewController = segue.destinationViewController as! ViewController
theVC.receivedString = "true"
}
Thanks
In your prepareForSegue you should use a condition to check segue identifier like:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "yourSegueToAnyController")
{
//do code for specific viewController
}
}

Navigation Between Two View Controller

I have two View Controllers. in mainViewController there is TabBarButton when it clicked user goes to 1stViewController and there is UIButton when it has clicked user goes to 2ndViewController.
before making my 2ndViewController everything worked fine. but after i add segue function in my program i got error.
could not cast value of type 'Calculator.1stViewController' (0x791a8) to 'Calculator.2ndViewController' (0x794c8).
briefly my code is
#IBAction func CalculateGpa(){
//Calucation Goes Here
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var AnotherName : 2ndViewController = segue.destinationViewController as! 2ndViewController
//Code here
}
UIButton Perform the segue and BarButton do nothing it just go to 1stView Controller. when i run the program and click BarButton im getting that above error.
its because prepareForSegue cant identify to which button it should perform right? how to solve it?
try this code.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "youridentifiername") {
//your class name
if let viewController: DealLandingViewController = segue.destinationViewController as? DealLandingViewController {
viewController.dealEntry = deal
}
}
}

Resources