Objective-c Conditionally serve ViewControllers after app launches - ios

I have a question about loading view controllers when an app launches. I want to have a condition that checks when the application launches based upon stored core data values and if true, it will load the view controller second in the stack. If false, I want to load the root view controller. I want to always preserve the root view controller not matter what the result of the condition, I just want to skip loading this view if the result of my condition is true and go right to the second view in the stack. I am not using storyboards. Has anyone done anything of this nature before?
Now, having said that, is this logic flow an acceptable solution to be implementing. Will there be issues during submission if I try something like this?

Let's say you have the following view controllers:
UINavigationController *navigationController;
UIViewController *firstViewController;
UIViewController *secondViewController;
Then you can write code like this (edit: reworked solution based on comments below):
if (yourCondition)
navigationController.viewControllers = #[ firstViewController, secondViewController ];
else
navigationController.viewControllers = #[ secondViewController, firstViewController ];

Early in your app's launch, like in -applicationDidFinishLaunchingWithOptions:, check the condition in question and, if true, push the second controller onto the navigation stack. Specify NO for the animation parameter so that there's no obvious transition.
You can also set the nav controller's viewControllers property directly. Set it to an array with first and second controllers if the condition is true, or just the first controller otherwise.

Check the conditions in the -applicationDidFinishLaunchingWithOptions: is the simple way.
However, we are suppose to keep the AppDelegate away from complicated. The best way to do the launching things, like check some condition, prepare the data, is to create a LaunchViewController as the rootViewController, you can make it the same looking as your app launch image. Then, you can presenting any VC you want with/without animation, it will be the first VC that user will see.
Let me know if you need more help.

Related

UINavigationController.set​View​Controllers is resulting in an empty viewControllers array

I am using the set​View​Controllers function on UINavigationController to set my first root view controller but the viewControllers array is empty after it has been called.
I know it is expected behavior to see the view controller in the viewControllers array immediately after setting, even if there is an animation so I'm not sure what could be causing the problem.
setViewControllers([viewControllerToPresent], animated: true)
Noteworthy: It is happening at app launch time but after I am certain the UINavigationController is loaded and ready.
The problem ended up being trying to simultaneously present a viewcontroller modally (tutorial slides) as the navigationcontroller was trying to push a viewcontroller on to the stack (both animated)
By delaying the presentation of the modals by 1 second, both view controllers were able to present without clobbering one another.
Would love to know the whys of this if anyone if familiar enough with UIKit and Animation APIs to explain. Will accept my own answer if I don't hear from anyone but will gladly change this if we get a better answer in the future.

UIViewController getting deallocated after dismissing a previously presented modal viewController

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?

Using segues right

I have read here a lots of questions and answers regarding segues and story board , and i became even more confused about the way i build the hierarchy between views
My questions are very basic and simple, and i think they may be helpful to others :
1.In a simple words, when should i use push , modal, or costume segues ?
2.When go from view1 to view2 to view3,how should i go back from 3 to 1? can i just drag a segue from 3 back to 1? and what happens with 2 and 3 with memory aspects in that case ?
3 when dismissing a view, why it always go back to the previous view? is there a way to make a segue that dismiss automatically the previous view ?
I think a very simple and short summing on the way it works would be so helpful.
thanks.
If you are using Storyboards and segues you may want to take advantage of exit segues for going back. In your example you want to go from View 3 back to View 1. Depending on how you got there, you may have multiple options to go back. For example, if you used a UINavigationController and pushed your way there, if View 1 is the rootViewController you could simply call popToRootViewControllerAnimated: and it would handle what is necessary to get from wherever you're at in the navigation stack back to the root. If View 1 is not the root you could opt to use the popToViewController:animated: API instead, assuming you have a reference to View 1 from View 3 which usually isn't ideal if you're keeping concerns separated. As Renish pointed out you do have the option of accessing the viewControllers property of your navigationController.
Back to Storyboards, for better or worse, they can handle this all for you via an exit segue. The storyboard configuration determines the proper way to go back to a view that you came from. Check out this great explanation in this answer, https://stackoverflow.com/a/15839298/250190
I think u want How to Go 3view to 1view.Simply make array of Your view controller.
How do I get the RootViewController from a pushed controller?
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/Reference/Reference.html#//apple_ref/occ/instp/UINavigationController/viewControllers
Use the viewControllers property of the UINavigationController. Example code:
// Inside another ViewController
NSArray *viewControllers = self.navigationController.viewControllers;
UIViewController *rootViewController = [viewControllers objectAtIndex:viewControllers.count - 2];
This is the standard way of getting the "back" view controller. The reason objectAtIndex:0 works is because the view controller you're trying to access is also the root one, if you were deeper in the navigation, the back view would not be the same as the root view.

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.

Using a UINavigationController for a set path without Back options

I am using a UINavigationController within my app (as expected) for a specific path the user takes when taking a turn in my turn based game.
When they move through the turn controllers they do not actually have the option to go Back from the Navigation Controller. This is planned/expected behaviour.
My question is, is it best to keep the other controllers on the UINavigationController stack when they are not going to be used again.
Should they be de-alloced immediately, or wait for the whole turn to be complete and let them go when the navigation controller goes (how it is at the moment). Some of the controllers hold data/images etc as properties so I am wondering if it would be more efficient to get rid of these on the fly?
If it is, what is the best method to load new controllers into the UINavigationController at present I am using self performSegue... or buttons that push to the VC from the storyboard setup.
You can manipulate navigation controller viewControllers using this code
NSMutableArray *viewControllers = self.navController.viewControllers;
//remove or add in the array
[self.navController setViewControllers:viewControllers];

Resources