OK, bear with me. I have a storyboard based IOS app that:
Framed as a TabBar main navigation. One tab segues to a NavigationController. Fine.
In the navigation controller main view I have a CollectionController, also good.
When selecting a Collection item, I "push" (from a different storyboard) a UIViewController that works like a charm.
From the UIViewController, depending on user action, I segue to a second UIViewController
From the second UIViewController, depending on user action, I attempt to push a new instance of the second UIViewController (basically push myself even though I instantiate a new blank one from the storyboard).
When I do this, I am brought to the view controller noted in #3 above.
I'm thinking it has to do with the segue from #4 versus #4 pushing using navigation controller. Anyone?
TIA
Frank
I don't think you shouldn't do it that way. You could either use an unwind segue to go back to that controller or do popToViewController:animated: in code to go back to that controller. This will go back to the same instance of that controller which may not be what you want.
If you really need a new instance, you should create a new scene in the storyboard. You can create this new scene by copy and paste on the one you already have -- that way, it will have the same view. After you copy and paste it, you can move it to where you want, give it a new identifier, and hook up its new segue..
Related
Summary:
I'm writing a Swift iOS app with a login screen and several other views in a tab view controller. I'm transitioning from one viewcontroller to another via the "control" + left click -> "Show" method. I want to make sure I'm not designing my iOS app incorrectly with memory leaks or other flaws.
Relative Questions:
Does this mean a new view of that ViewController is created each time "Show" is called?
Could this cause a memory leak or the app to crash?
Do I need to unwind the ViewControllers at some point?
What is the best way to unwind a ViewController when launching another ViewController?
It seems what you are talking about is manually creating a Show Segue (a transition, made via the Storyboard with ctrl + click and drag to another ViewController). This is one correct way to create a Segue (transition) from one ViewController to another. To utilize this, you will need to use the left panel on the Storyboard, give this segue an identifier, and use this identifier to preform a segue from the first ViewController to the second in some sort of method or action (like a button click, etc) using the performSegue method:
self.performSegue(withIdentifier: "NameOfSegue", sender: self)
Here's more info on segues from the docs:
https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html
You can read even more detail in the "Modifying a Segue’s Behavior at Runtime" section. Here's a quote: "Most of the work happens in the presenting view controller, which manages the transition to the new view controller. The configuration of the new view controller follows essentially the same process as when you create the view controller yourself and present it." Memory leaks shouldn't be an issue here. Unwind segues let you dismiss view controllers that have been presented, but they are not always needed.
I am using swift to perform segue programatically. First, I created a segue between two controllers in storyboard. Below is the code to show a view controller:
self.performSegueWithIdentifier("EditImage", sender: imageSampleBuffer)
When executing the above code, a new controller view will be presented on the UI. Then I click the "back" button on the top-left corner. The ui will come back to the previous view. It works fine here. But when I profile my app with instrument I found that the controller(pointed by "EditImage" segue) not released. When I click the controller instance on instrument, it shows that the above code is referencing this controller instance. When I perform these two controller back and forth, the instance number of that controller keep increasing. I didn't create any action function for the "back" button. All uses the default logic with navigation controller. So how to release controller when come back? Should I write any code on go back action?
In the UIViewController that is not been release add a deinit method and place add a breakpoint there, you will find if there is any other object keeping that reference form outside. Any public var could keep that reference, that's why all delegates should has weak reference. example
I did find a reference problem in my code. I cleared that reference in viewDidDisappear() method then it works fine. But I don't understand why instrument didn't give me the correct place where is holding my controller instance.
I have a category on UIViewController that deals with errors coming from my networking layer. If I get an authentication error in response to a network call, I want to perform an unwind segue which takes me back to my LoginViewController.
However, I don't want to have to add the appropriate unwind segue to every single view controller in my Storyboard. Can I simply declare the unwind segue in the UITabBarController that is at the "top" of my view controller navigation, and then say
[self.tabBarController performSegueWithIdentifier:#"UnwindToLoginSegueIdentifier" sender:self]
... from inside my UIViewController+ErrorHandling category?
No, you can't do that. The unwind segue has to come from the controller you're unwinding from, and all segues need to be connected from a particular instance in the storyboard. The login view controller really should be one that's presented modally, not be one of the tabs, since you only need it briefly, then it should go away. If you set up your app that way, you can present and dismiss it from any controller (present it without animation from the controller in the first tab, if that's what you want the user to see when the app launches). You'll still have to have code in every controller to do that, unless you make a common base controller with that functionality that all the other controllers inherit from.
I'm new to iOS dev and am not entirely sure on Storyboards/Segues/Pushing and Popping.
So in my app I have a navigation controller with 5 view controllers leading from one to another.
When it reaches the last view controller i have a segue to the first and I have a few tasks listed in the prepareForSegue method.
Out of curiosity I decided to check what happens to the [self.navigationController.viewControllers count]. I found that it keeps growing and growing which doesn't 'feel' correct.
Am i handling going back to the first screen correctly? The prepareForSegue method is useful as it allows me to send some data back to the first segue. Is it possible to maybe say when you go back clear all views on that navigation controller?
Thanks
You can use an unwind segue. Here's a good tutorial:
pragmaticstudio.com/blog/2013/2/5/unwind-segues
Make sure to create the unwind action method before you wire it up in the storyboard otherwise it won't show up when you drag to 'Exit'. That was the most confusing part for me when I first set one up. The tutorial does it in the correct order so if you follow it you should be fine.
Also, here's a sample I put together showing how to transfer data back in an unwind segue. It uses a modally presented view controller but the technique is the same:
github.com/soleares/AddToTableView
No, you should never go backwards with a segue (other than an unwind). Segues ALWAYS instantiate new controllers, so you're not actually going back to the first controller, you're just creating a new instance, which gets added to the stack. So either go back with an unwind segue or use popToViewController:animated:. Using an unwind segue will allow you to use prepareForSegue, and it does cause all the controllers in between to be deallocated (if you have no other strong pointers to them).
Now, I have a table view called Products with a add button on the navigation bar. When click on add button, the new view controller will be pushed to show which called AddItem. Here is the thing, Can I open a new view controllers A from AddItem and reopen Products from A?
May be my description a little bit confused.
ProductsTableViewController --(Push)--> AddItemViewController --(Modal/Push)--> AViewController --(Modal)--> ProductsTableViewController(Should be exact same as the first one)
And there may be some controllers between AddItemViewController and AViewController.
I have two solution:
1. When open ProductsTableViewController from A, get the same instance as before
2. Create a new instance of ProductsTableViewController and get data from an singleton class.
My concern is that is there any memory leak or protential risk?
your best bet is to use delegates. not sure why you want to do this, but if you have all your vcs in the stack, and your "ProductsTableViewController" is the root, then just have it move to the top of the stack.