UIViewController getting deallocated after dismissing a previously presented modal viewController - ios

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?

Related

presentModalViewController vs pushviewcontroller memory cosumption

I have two method to jump from one viewcontroller to another
For presentViewController
[self presentModalViewController:view animated:YES];
For pushViewControlle should use
[self.navigationController pushViewController:view animated:YES];
Which Will be best approach ?
Which will cause more memory leak?
Which one is use if Our Design is like
Introduction view (bunch of slides )-> login -> signUp-> HomeActivityScreen-> Then Bunch of tab bar in it
If you use pushViewController you will automatically get a "Back" button in the navigation bar. If you use presentModalViewController you do not, and generally will have to implement your own controls and/or callbacks to handle dismissing the controller.
Conceptually the modal presentation style is generally used for atomic tasks that you cannot navigate away from (i.e. you either complete the task, or you cancel, and you cannot do anything else within the app until you do one or the other).
If you're wondering why have the difference in the first place, I can't say. Personally I think frameworks that provide a unified API for moving from one controller to another (like cocos2d, or Android) make a lot more sense.
You use modal view controllers to focus the user's attention on a Task. When you push, the user is in some kind of navigation flow, but still has the total application at their fingertips. They might decide to go forward or backward, switch to a different tab in the middle, whatever. When they get a modal view controller, they can't do any of that until the task is completed or canceled out of (the modal view is dismissed)
When you present a modal view controller, the system creates a parent-child relationship between the view controller that did the presenting and the view controller that was presented. Specifically, the view controller that did the presenting updates its modalViewController property to point to its presented (child) view controller. Similarly, the presented view controller updates its parentViewController property to point back to the view controller that presented it.
Modal view controllers provide interesting ways to manage the flow of your application. Most commonly, applications use modal view controllers as a temporary interruption in order to obtain key information from the user. However, you can also use modally presented view controllers to implement alternate interfaces for your application at specific times.
So, from my understanding this one is best option.
[self.navigationController pushViewController:view animated:YES];
Apple handles the memory for both of these through Automatic Reference Counting. Although pushing a view controller might require more memory than presenting the same, the allocated memory is released when popping or dismissing the ViewController. ARC releases the said memory if no strong references are made from within the popped ViewController, or in other terms, the ReferenceCount is 0. So care must be taken so that no strong references are retained to the ViewContoller's objects.
Now whether to present or push a ViewController depends solely on your app design. Read this to get an outline on when to present a ViewController, .
They are two approaches to navigate from one view controller to other view controller.
By default:
- pushviewcontroller: you will have a back button to return to last visited page. your viewcontroller is put on top of the navigation stack. Think like a webpage when you navigate between pages.
- presentmodalviewcontroller: you have nothing to comeback to last visited page. It is usually used for: a pop-up or to change to new branch of navigation.
The use of pushviewcontroller & presentmodalviewcontroller does not produce memory leaks.
For your application flow, I suppose that HomeActivitiesScreen is one of viewcontroller in your "bunch of tab bar". If so, create a viewcontroller that contains that tabbar and make it as root of your application (named RootViewController for example). Then:
When application is launched, you show the RootViewController
And immediately, present the modal view to your "introduction pages", then login/signup. This modal view start with a Navigation view controller structure.
When the user is connected, dismiss your modal view, return back to your HomeActivitiesScreen and refresh contain if need.
Like this, you do not keep the reference to your login/signup screen when you do not need.

ViewWillAppear & ViewDidAppear firing when dismissing ViewController

I am making an iOS app where I want to present a flow of pages like this:
Basically I want to achieve is to have this flow of pages:
PageA
PageB
PageC
PageD, dismiss back to:
PageC
PageD
PageE, dismiss back to:
PageA (starting point, start over again)
I am using ShowViewcontroller to present the pages (modal) and DismissViewcontroller to dismiss.
As per Apple's documentation if I dismiss a VC early in the stack all subsequent UIViewCOntroller are dismissed too (Apple doc).
However I experience that ViewWillAppear and ViewDidAppear are fired on the UIViewController that are dismissed even when they do not appear (e.g. in the example when dismissing back to PageA from PageE then ViewWillAppear is called on PageD, PageC, PageB too).
This does not seem logical to me. Can anyone explain why this is happening? And perhaps correct me if I am approaching this the wrong way.
I am using Xamarin.iOS.
Apple doc:
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.
The ViewControllers work with a stack. Whenever a new ViewController (of any type) is added to the stack, You lose more and more control of your ViewControllers (especially when using a modal for your ViewControllers). So, say you have 5 ViewControllers in your stack (A, B, C, D, E, as per your example), and assume they are created in the order as stated, in order to return from ViewController E to ViewController A, you'd have to go through the entire stack. That means that every ViewController in your way needs to be displayed first, in order to dismiss is (since you already have ViewController E displayed, this doesn't occur here).
I hope this helps you. Good luck!
Love and regards,
Björn

My Navigation Controller Count Keeps Growing

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).

Skipping view controllers in a UINavigationController stack

Is it bad practice to skip view controllers in a navigation stack?
In my example I have a UINavigationController (which is being presented modally) with three UIViewControllers (firstViewController, secondViewController and thirdViewController), most of the time the user will be accessing firstViewController, maybe tapping a row which will then load secondViewController and so on, but what if in some circumstances I want to load the second or third view controllers immediately but still keep the first view controller in the stack, so that the user can still go back to the firstViewController.
I can do this but it doesn't feel right - is this something I should avoid doing?
Yes, it's called deep-linking, and it's perfectly fine. It's quite commonly done for things like coming from an external URL or push notification.

Modal ViewController presenting another viewController won't animate immediately

Yes, I struggled a bit with that title...
Here's what my setup is meant to do:
I push a viewController (resultViewController) onto the navigation stack. Immediately (literally in the next line of code) I present another viewController to the rootViewController (filterViewController).
So far, so good, and things work as expected.
The modally presented viewController contains a tableView. Selecting a cell is supposed to present another viewController in the current (filterView) controller.
[self presentViewController:filterDetailsController animated:YES completion:^(void){
}];
This is where things go awry: The above snippets is called at the correct time, but the viewController does not appear until I perform an additional tap or gesture somewhere in the filterView. This suggest that the stacking of modalView inside modalView somehow messes things up. If I change the animated parameter to NO, the viewController is presented immediately.
An obvious work-around would be to set animated to NO and perform a manual animation in the completion block. I would however love to see if anyone have come across anything similar and knows how to fix the problem.

Resources