View Controller Setup - ios

I am trying to figure out the best way to get my view controllers setup according to the design I am given. My app starts off with a full screen login screen. The user logs in and then the next view is a 3 tab screen. Where clicking on any control in any of the 3 tabbed view, need to take you to a full screen view controller.
Now the problem I am facing is that
1) The guidelines say not to put a TabBarController in a NavigationController, which in this case I have to do.
2) Also If I set the ViewControllers of each TabBarView to be a navigation controller, then I don't get the full screen space as the bottom always shows the tab bar, which I don't need to see.
Thoughts and pointers gladly appreciated.

The way that I would set it up would be to have a global container view controller that manages all of the internal view controllers. Example:
=============================
= Container View Controller =
=============================
| |
------------ -----------
- Login VC - - Main VC -
------------ -----------
Then, the workflow for app launch would be as follows:
Application launches and the container/splash view controller is the root view controller.
Container view controller determines login status (shows a loading indicator perhaps, etc).
Transition to the correct view controller.
If the user is not logged in, you could transition to the login view controller. From there, you could subscribe to either a delegate callback or a notification which would be dispatched once the user logs in. Once that message is received, you could re-check the login status and show the view controller accordingly.
If the user is logged in, at either the start or after receiving the login callback, then just show the main view controller.
Logout would work the same way as login. Just push a notification to the container view controller and have it manage the view controllers accordingly.

Personally, I would use a tabBarController as your initial view controller. If the user is not logged in, immediately present (modally) your login view controller. Dismiss the login controller once the user has logged in, and return to the tabBarController. Wrap the view controllers for each tab in a navigation controllers, but set hidesBottomBarWhenPushed in order to hide the tabBar.

Related

What happens to a View Controller after it has modally presented another View Controller

Consider the following structure of an app:
Login Screen --> Splash Screen --> Main use (--> Logout page --> New Instance of Login Screen)
When the user logs in from the Splash Screen, I present the Splash Screen Modally from the Login Screen. When the Splash Screen have completed it's tasks, I present the Main Use View (Which is a UITabController) modally from the Splash Screen. If at some point the user decides to logout of the app, I remove the credentials and present a new Instance of the Login Screen modally from the Main Use View.
I recently started doubting that this works as I expect it to. Say that the user have navigated all the way to Main Use, are the presenting View Controller (Splash Screen) and it's presenting View Controller (Login Screen) still active and present in the Hierarchy? After Modally presenting another View Controller, I expect the first View Controller to be completely unloaded and forgotten by the System, as if it was set to null. Can someone confirm this? And in case this doesn't work as I expect it to, what should I do instead of modally presenting View Controllers?
Your doubts are warranted. When you present a modal view controller, it goes on top of the existing view controller and covers it, but the existing view controller does not go away. You never want to present a new copy of a view controller without dismissing the previous one.
(Using dismiss(animated:completion:).)

How a Page View Controller can pause the Root View Controller from running. (xcode)

My app starts with a View Controller (Initial). On this View Controller i display a countdown message (using NSTimer and scheduledTimerWithTimeInterval) that is auto-initiated when the user opens the app (viewDidLoad method).
In the settings menu (a second View Controller (modal segue to the initial) a have a "Tutorial" menu choice that leads to a Page View Controller that handles a couple of View Controllers and presents them as Form Sheets). The last page of this Page View Controller has a button "OK" that dismisses the Page View Controller (so that brings you back to the Settings menu according to my Storyboard).
So far, so good.
Now when the user runs the app, i call from my initial View Controller the viewDidAppear method and using NSUserDefaults i run a check if this is the first time the user runs the app. If YES it creates an instance of the Page View Controller that displays (as form sheet) the Tutorial. And here is my problem..The initial View Controller is running at the background as expected to do so.. but how can i pause the countdown message until the user dismisses the Tutorial (by pressing the OK button)?
NOTICE: I've just noticed that if you change the page view controller
presentation as "Full Screen" or run the app on the iphone instead of
the ipad (forced full screen presentation) the app is running normally, but that,i
assume, is because in this case (full screen presentation) the initial
view controller won't load until the page view controller is being
dismissed!
I think that your PageViewController has a reference to his parent view controller (InitialViewController), so you have to define your NSTimer as a InitialViewController property.
You can use global app notification system to let know your rootViewController about external events. Check out NSNotificationCenter class reference.

UINavigationController limited utilization in app design

I am using the NavigationController (Embedded via Editor drop down menu in xCode) to control navigation on sign-up and sign-in views, all from landing view when app first launched.
After user sign-up or login, I would like to initiate a view controller with no relation to the NavigationController. Nonetheless, from Sign-up and Login views, I have a segue that links (upon successful authorization) to the main view of logged in users. How can I remove the navigation controller from a certain part of the application because it is no longer needed? Otherwise, each time I add a new view controller, it shows the navigation bar in it which is not ideal for design.
Thanks and image attached shows what I need illustrated.
As far as I am concerned you can remove only view controller from navigation stack. If you do not want navigation bar to be visible, then just hide it in viewWillAppear of view controller that you want to be without navigationBar.
[self.navigationController setNavigationBarHidden:<#(BOOL)#> animated:<#(BOOL)#>]

How to skip a login view controller?

I develop an iOS app and my initial view controller shows a login form. Then when the user successfully authenticates the actual application is presented as a modal view controller.
When the user logs out the application it is dismissed and the login view controller is visible again.
My problem is:
When the application is started again and the user already is logged in I don't want to show the login view controller. I can't present the view controller before the login view controller is fully shown:
Warning: Attempt to present <UITabBarController: 0x10a271b40> on <LoginViewController: 0x10a2594f0> whose view is not in the window hierarchy!
I can present it with a delay but this is not what I want.
I could check if the user is logged in before I show a view (in the app delegate) and then show the login or the application. The problem with this is:
When the user logs out I have no login view controller beneath my application to which I can pop.
I can't find a good solution except defining the actual application as the root and present the login over it. But this brings a lot new problems because the main application needs data structures I can only initialize after login.
You don't want to be running with a modal always shown, it will be easy to inadvertently dismiss your 'entire app'.
Instead, do as you suggest in the app delegate where you decide which view controller is required and change the root view controller of the window. Again, when the user logs in / out, change the windows root view controller.
Most Application flow will be like that.
1) Set your tabbar controller as rootviewcontroller. When application launch, check with login status and show your tabbar(rootviewcontroller) if already logged in. Otherwise present modal view as loginview controller from tabbar(tabbar is rootviewcontroller).
2) When logout success, again show loginView as modal view(tabbar is rootviewcontroller).
Note: You can also shift rootviewcontroller as tabbar and loginview. But I recommented above flow.

Using UISplitViewController in iOS

I want to add a split view controller when the login button is clicked on the login screen (when user is successfully logged in). I want to show another view controller which is a split view controller with a master controller and detail controller.
SplitViewControllers are intended to be used as the root view controller. So you will need to create your login viewController and attach it to the window. Then when the user logs in you will have to remove the login viewController and then create a new SplitViewController and attach that to the window instead.
If you search you should find threads that help e.g.
How to implement SplitViewController on second level.?
I know there are also threads showing how to do this for tabBarControllers and the process is the same.

Resources