I have a iOS5 storyboard app and am using it to push a view controller 'B' onto the navigation stack when a particular button is pressed in the initial view controller 'A'. After the button press 'B' gets loaded with some data pulled from a Web Service.
When the user hits the back navigation button and then presses the button to go to back to 'B', B has been completely reset. I understand that this the Storyboard recreating the ViewController B. How do I stop this from happening? I'm looking for the right design pattern to solve this problem.
Just to clarify why this happens. As soon as you hit the back button, the viewController 'B' is pushed off the stack and thus removed from memory. In order to avoid this, you will have to create a strong pointer property to the viewController 'B' in your AppDelegate. Then in viewWillAppear, you check to see if this property is null, and if it is you set its values normally. If it is not, then you know that you already have the viewController ready, and you use that instead.
Related
I have two view controllers A and B and a segue from A to B (type: show) through a next button and a segue from B to A (type: show) through back button. I am passing some data through segue A to B. Data is displayed correctly if I just tap next from controller A and go to controller B.
However, If I tap next and go to controller B and hit back and come back to A and then hit next again, it doesn't work. Any ideas whats going on here? Sorry for the confusing language.
Sounds like your "B to A" is wrong, you're using a navigation stack so you should only push (show) when you are moving forwards. When going backwards you should pop off the top (dismiss)
If you keep pushing, the app will continue to just put more and more ViewControllers in memory, which is bad.
I suspect whats happening here is View A initially has the data and passes it to View B. Then when you press your back button it creates a new copy of View A which doesn't have the data and shows that instead of the original View A.
In Short: (A to B :type - show) (B to A :dismiss the current ViewController)
I agree with user2877496 in that you should not use a regular segue to go back from B to A as you will be adding "A" onto the stack each time.
I just wished to add that one method to dismiss B and go back to A is by using an Unwind Segue.
The Apple documentation covers this quite well
https://developer.apple.com/library/content/technotes/tn2298/_index.html
Did you resolve this? My guess is you put stuff to execute in viewDidLoad (which only runs once at the start of your app) and it needs to be in viewWillAppear so it is called each time you return to your main view controller. Please provide your code for those methods if you require further help.
I have a MainViewController which is a table view controller, with custom cells where the user can select some data. There is a button on this MainViewController that goes to PreferencesViewController, which has two buttons on the navigation bar, one for back (it is wokring now good), and the other one for save (here is my problem)
This is a screenshot of the navitation bar in the PreferencesViewController:
I drag a segue from the save bar button back to the MainViewController.
my problem
when I hit save, the MainViewController appears, but without saving the values the the user has already selected. sounds like a new instance of this MainViewContoller is being created.
What am i missing here? what other approach i should have already used please?
You need to connect your save button to an IBAction, not a segue.
In that IBAction, do whatever you need to do to save your data, and then do a dismissViewController:animated: call yourself in code.
If you wanted to use a segue you wouldn't be able to (easily) save your data, and yes, it creates a new instance.
An alternative would be to connect your save button to an unwind segue, rolls back, or unwinds, one or more segues to get back to a previous view controller. To do that you'd have to put your save logic in prepareForSegue (with code to test which segue is being invoked and only save in response to the save segue.)
i found the solution myself using:
1- custom delegate:
2- self.navigationController?.popViewControllerAnimated(true)
From an initial ViewController I've modally presented a second ViewController using a ShowDetail segue in the storyboard and a performSegueWithIdentifier: method call. The problem is when I dismiss this modal ViewController with the method dismissViewControllerAnimated: the initial ViewController is reinstantiated calling the viewDidLoad again.
I've tried using a Push segue instead of the Show Detail and the initial ViewController keeps allocated in the background as it should.
What might be going on? The initial ViewController never even calls the memory warning method.
Have you tried unwindSegues?
***** Long explanation ahead, skip to solution if you want the quick way *****
First of all, if it is a ShowDetail, it is not a modal view. Do try to see which is your case.
Modal segues can carry information backwards, but are a bit more complicated than push ones.
If you are modally presenting it, you should use Present Modally instead of a ShowDetail.
A modal presentation will always take the top view position in the stack, and Show Detail does as well, depending in how your views are set. For instance, if you have a detail view in stack, IT will be replaced rather than the stack top view.
Try choosing up to a specific segue, I particularly recommend modal assuming you need more than simple pushes (Or the Show would have closed the problem, being the equivalent to the previous deprecated push. If you only need something simple, Show is the way)
Now we've cleared this, what probably is happening is that the view is being removes since Show Detail replaces views instead of pushing them, and it has to perform init again.
***** Solution: *****
The solution then should be not to lose the view when replacing, and reinitializing it, what dismissViewControllerAnimated: does. If you use unwind segues, though, the view should be replaced BUT retained by ARC.
The following link has the best explanation all over the net about how to use it:
What are Unwind segues for and how do you use them?
I have two ViewControllers. The first has UITableview that I push data from to the second ViewController. Whenever I go back, the first ViewController loses its properties - Its navigationbar background disappears and for example the sidebar menu does not work either. Is there any way I could reload it while pushing the back button?
Thank you
Sounds like you are probably doing your setup in viewWillAppear instead of viewWillLoad. This means that when the view will appear on return, the setup is happening again and perhaps leaving you in an unexpected state. Put breakpoints in your view controller delegate methods and see what order things are being called in and why.
I have 2 views, A and B. A is a tableview, and B is a detail view. When a cell is tapped in view A, the appropriate data is loaded in view B and I use [self.navigationcontroller pushviewcontroller] to present it. This all works fine, but if the user presses row 10, lets view B load, goes back, and presses row 10 again, I would like for it to just go forward to the view B that is already loaded. The navigationcontroller always lists as only having one view in the stack. Do I have to manually save a view to the navigationcontroller to re-present? The project uses ARC and Storyboard if that makes a differance. Thanks
For this actually you dont even have to concern yourself with navigationcontroller. Have a UIViewController variable (lets say lastViewController) in your ViewController1 where viewA and viewB reside.
Before pushing ViewController2 the detailed view store that reference in lastViewController. When you pop back and press another row, check if its that same viewController and show the same viewController.
But I would advise against this approach. Keep it simple, let ViewControllerB load again. There could be a scenario where loading again is preferential as it might show the user more latest information row10.
The behavior you are seeing is correct! When ViewController B is needed it is created and pushed onto the stack of the navigation controller and we see view B. When the user goes back to ViewController A and we see view A, ViewController B is no longer needed, and it and its view go out of existence.
This is efficient and lightweight and makes perfect sense. Once you are back in ViewController A and view A, who knows what row the user will tap now? If the user taps row 10 and goes back to A, taps row 10 and goes back to A, over and over, a new ViewController B will be created and go out of existence each time. So what? From the user's point of view it is perfectly consistent; it looks like the same view B! That is all that matters. You don't want to go back to the same view B; you want to create view B all over again. And that is what you do.
Indeed, this is the genius of iOS. With a single tiny screen, it is able to make views come and go without burdening memory and other resources.
For more about UINavigationController architecture, which is what you're using here (master-detail), see my book: http://www.apeth.com/iOSBook/ch19.html#_navigation_controllers