Swift 5 - Middle view controller briefly appearing - Should remove? - ios

Setup:
Initial view controller A has a menu button that goes to VC B, which then has a button that goes to VC C. On C, I have an exit button that takes me back to A. In this transition, B briefly appears. The two things I'm trying to figure out is:
How do I keep B from flashing on the screen?
and
Is B off the call stack and releasing the memory?
This is what I'm running to get rid of the C and go back to A:
#IBAction func backButtonPressed(_ sender: Any) {
self.view.window!.rootViewController?.dismiss(animated: true, completion: nil)
//performSegue(withIdentifier: "exitToMainScreen", sender: self)
}

I found a work-around for this glitch.
In VC B, I encapsulated everything in a view attached to an outlet. So when I perform the segue to VC C, I set the view's isHidden = true. When the unwind from C to A occurs, the view in B is hidden and does not appear on the screen in transition.

Related

Close a viewcontroller after a segue

What I want is to close a viewController after performing a segue so that the back button of the navigation controller on the new view doesn't go back to the view that I just closed, but it goes to the view that precedes it in the storyboard like it is the first time that it is loaded.
I already tried stuff like dismiss and so but it doesn't really work for me as it only closes the view in which the button that I pressed for performing the function is located :
#objc func goToList(){
self.dismiss(animated: true, completion: nil)
performSegue(withIdentifier: "goToList", sender: nil)
}
The navigation controller maintains a stack (array) of ViewControllers that have been opened (pushed). It also has the ability to pop these ViewControllers off the stack until it gets to a specific one.
For example, if you wished to return to a previous view controller of type MyInitialVC then you'd want to search through the stack until you found that type of VC, and then pop to it:
let targetVC = navigationController?.viewControllers.first(where: {$0 is MyInitialVC})
if let targetVC = targetVC {
navigationController?.popToViewController(targetVC, animated: true)
}
NB. written from memory without XCode, so you may need to correct minor typos
You can use unwind segue to get back to each viewController that you want.
Read more here:
Unwind Segues Step-by-Step (and 4 Reasons to Use Them)

Double return to previous view - Swift

I'm new with IOS and Swift so don't judge if solution is easy.
I have three ViewControllers like A,B and C.
I started from A -> NavigationController -> B -> NavigationController -> C
In specific situation I need to come back from C to A without seeing B. Is any way to do this?
Maybe changing the parent navigationController? Maybe I can print stack with every current view? - it will be really helpful.
I tried dismiss C and B view one by one and it work's but then we can see B view for a moment - so it's not a solution for me.
P.s : I'm using Modal kind to switch between controllers.
enter image description here
If A is always the first view controller, you can just do :
viewcontrollerC.navigationController?.popToRootViewController(animated: true)
This methods pop the stack to the first view controller, without displaying intermediates ones
If A is not the first viewController, you can do :
viewcontrollerC.navigationController?. popToViewController(viewControllerA, animated: true)
If you don't have a reference to viewControllerA, search it in the stack :
let viewControllerA: UIViewController?
for (let vc in (self.navigationController?.viewControllers ?? [])) {
//adust the test to find the appropriate controller
if vc.isKindOf(ViewControllerAClass.self) {
viewControllerA = vc
break
}
}
if let viewControllerA = viewControllerA {
self.navigationController?.popToViewController(viewControllerA, animated: true)
}
source : https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621871-poptoviewcontroller
There are 2 ways you can achieve this. The simple to implement is in View Controller C you can, on in the specific situation, invoke following function:
navigationController?.popToRootViewController(animated: true)
This will pop all the navigational view hierarchy and take you back to the root i.e. the first view controller.
Second approach is to define unwind method in the view controller you want to go back to. In view controller when you start typing unwind, in Xcode 10 you will get autocomplete to add this Swift Unwind Segue Method.
#IBAction func unwindToA(_ unwindSegue: UIStoryboardSegue) {
let sourceViewController = unwindSegue.source
// Use data from the view controller which initiated the unwind segue
}
In this particular question let us say you added this method in View Controller A as you want to go back to it. I assume you have a button on View Controller C to go back to A. Controll+Drag from the button to the Exit symbol of the view controller A. The unwindToA method will automatically pop-up. Connect to it and you are done. When the user presses this button it will go back 2 navigation controllers to A.
Note: By this method you can go back to any navigation controller on the Navigation stack and it is not limited to root view controller alone. Below I am addition picture showing the exit on a view controller.

xcode 8 swift: unwind segue transfer data is not working

So I have been trying to get a unwind segue to work from last two days. I have tried watching and follow several different tutorials and none was successful. I created the #IBAction override func unwind(for unwindSegue: UIStoryboardSegue, towardsViewController subsequentVC: UIViewController) but this never performs any of the code. I put a simple print and had it print text, it never printed the text. I created that in the first View Controller then in the second View Controller I had a button that I connected to the Exit at the top of the View Controller and selected the unwind action and it never unwinds. What am I doing wrong or missing?
So here is what I have so far I have 2 views: RaceViewController & SingleStatViewController
I will start by selecting specified rows in RaceViewController and they will open SingleStatViewController modally. I have a button in SingleStatViewController called dismissBtn. When I click the button it dismisses SingleStatViewContoller. I just need it to pass some data back to the RaceViewController.
So if the user selects 1 of 3 cells in the table (the rows are Half-Orc, Half-Elf and Human) it will open SingleStatViewController and ask to select 1 stat (these will be of 6 buttons (Str, Dex, Con, Int, Wis, Chr) when they select the one of the buttons it will return the data and update the detailTextLabel.
I select Human then I select Str. When it gets back to RaceViewController and it updates the text in the detailTextLabel to +2 Str.
Right now, this is the code I am using to dismiss. Can I use this to continue or do I actually need to perform the unwind:
#IBAction func dismissbtn(_ sender: Any)
{
dismiss(animated: true, completion: nil)
}
You need to perform unwind and send data as following:
#IBAction func unwindToRaceViewController(sender: UIStoryboardSegue)
{
if let sourceViewController = sender.sourceViewController
as? RaceViewController {
stat = sourceViewController.stat
}
You could refer to this article for unwind segues as alternative to delegate
You could also use delegates to pass data back to the previous controller.
Okay, so you have vc A and vc B, this is what you need to do to use unwind segue:
In vc A, create a segue function eg. #IBAction func unwind(segue: UIStoryboardSegue)
In vc B, write code that call self.performSegueWithIdentifier("unwind", sender: self) (assume that the identifier and the function name is the same - call this in your dismissbtn)
In vc B in storyboard, look on top of it, there will be an yellow button and 2 orange button, hold and drag the yellow button to the Exit orange button, choose the action that you created in vc A, give it an identifier as mentioned
In the unwind func, the rest is the same as normal segue when you pass data forward, just change destination to source and you must present vc B from vc A, else then use delegate

Dismiss view controller from unwind segue

I have 3 view controllers. I can go from A to B, then from B to C. I've made an unwind segue from B to A. When it's performed, I can see that view controller B has been deallocated, and VC A appears on screen.
To make it I added next code to VC A and made unwind segue on button in VC B.
#IBAction func unvindSegueToMenu(segue:UIStoryboardSegue) {}
However, when I go to VC C (from B) I want to perform unwind Segue from VC C to A. To do that I put next code to VC B class.
#IBAction func unvindSegueToMainMenu(segue:UIStoryboardSegue) {
self.dismissViewControllerAnimated(false, completion: nil)
}
After I press button in VC C, it shows me VC A as I want, but in Allocation Summary I can see that VC B has not been deallocated.
What is my mistake and how can I deallocate it?
Normally you made something wrong in your code.
i tested and i can see clearly that VC B is deallocated after performing the unwind segue.
First be sure that you made it right. (for example the performed method of the unwind segue should be implemented in the destination VC)
Also you can check after performing the unwind how many viewControllers you have in the navigationController..in your case should be 2 , but if you do it in the right way it will be only one.

Unwind to specific instance of ViewController

I have a ViewController that I'm just re-instantiating to navigate to another instance of it (there's a reason for this) with the following code:
let viewController = storyboard.instantiateViewControllerWithIdentifier("CompletionViewController") as! CompletionViewController
self.navigationController?.pushViewController(viewController, animated: true)
Everything works fine, except when I try to unwind... since every instance of the control has the unwind method:
#IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {}
It ends up unwinding to the last instance of the VC instead of the first (which is what I want), for example:
vc1 > vc2 > vc3 > unwind from here
I want to unwind to "vc1", but it actually unwinds to "vc3".
Is there anyway that I can unwind to the first instance of the VC; or like in my example "vc1"?
in your CompletionViewController, there are 3 icons at the top of the view. if you CTRL drag from the left yellow icon to the right red one (the "exit") you can choose your unwinding segues. Now you can use that unwind in your code ;)

Resources