In my app, things start off with a registration flow, including profile creation, mobile verification, and some further customization which all happens inside separate UIViewControllers managed by a UINavigationController.
However, when registration is completed, I want to leave the UINavigationController and have my final registration View Controller segue to the main TabBarController of the application.
How can I do this?
When you are using a navigation controller that controls more than one UIViewController, you use push push segues. When you want to leave that navigation controller, you will have to use a modal segue. I'm assuming that you are using the Storyboard. When you click and drag from one UIViewController to the next, you choose modal instead of push.
Segues are useful for prototyping, but for a real app I would avoid using segues and control the display of view controllers programmatically.
In your case, you could make the TabBarController the main entry point, and then detect whether the user has registered, and if not, display the registration sequence (modally) on top of this, and when the user completes the sequence, just dismiss it and you'll be back to TabBarController.
Or you could make your initial view controller a blank screen which then decides whether to display the registration sequence or the TabBarController.
Related
Is it possible to launch an app to a specific level of a navigation stack using a storyboard?
I'm looking to recreate the model employed by Mail.app, where the app launches into the Inbox, but this is actually one level down the navigation stack, and tapping the back button takes you to the root...
I understand how this can be done via code, i.e. instantiating the navigation controller within the app delegate and then manually pushing the view controller(s) to create the desired stack, but I'd really like to know if there's a way to achieve the same using storyboards.
Unfortunately I don't think there is because you need to instantiate your navigation controller at some point that will house your view controllers, and if you do this through storyboards the best you can do is set the navigation controller to be the entry point.
However, it is pretty straightforward to do from code. If your navigation controller has two view controllers where ViewControllerOne pushes to ViewControllerTwo, then you can just can just push to the second one without an animation as follows:
navigationController.pushViewController(secondViewController, animated: false)
And the user will be one level deep in the navigation controller.
I have a TabViewController setup in my iOS app with 4 tabs. Some of the tabs go to static ViewControllers while a few go to a navigation controller that the user can then dive deeper into.
My problem is this, in the app delegate, I implement the "didReceiveRemoteNotification" method, when I receive a remote notification I display a drop down notification using a library similar to this https://github.com/terryworona/TWMessageBarManager
I would like the simplest and cleanest way to add a callback to one of these drop down messages such that when clicked I display a particular index in the tab view regardless of where I am in the app.
I have thought of possibly having the app delegate broadcast a notification that the currently displayed view controller would listen too, then have the currently displayed view controller unwind if it is nested in a navigation controller to the top level, i.e. the level where the TabViewController would be displayed and then change the tab view controller's index. Or if the TabViewController was currently displayed, it would capture the notification and simply change index. But this seems conceptually intrusive because now my ViewControllers themselves must have knowledge about where they are in the UI hierarchy, and all ViewControllers (which there are many) must implement functionality to deal with the notification so they can decide to unwind + set tab index OR simply set tab index.
I would subclass the TabBarController, and you could add a method like -(void) receiveMessageBarNotification:(NSNotification*)notification. The TabBarController already has references to your view controllers and so can handle all the logic of 'navigation controller stack vs static VC'. Then it would call the unwind segue on the view controller (if necessary) and change its own index.
The notification registration could all be handled by the AppDelegate.
I am developing an iOS app that I have already developed for Android.
The problem is I don't know how to organize my UIViewControllers considering the following scheme of my app pages:
The scheme is simple: there is a login page which leads to the main page. From this main page, there are four buttons which all lead to a specific view hierarchy but at the very bottom of each, the user will be able to go back directly to the main page. Each page accessed by the main page will also have a custom back button (an image of my own)
The question is: is there any benefit in using a UINavigationController (obviously with the main page as its root) in my case? Or can I simply create each Controller and using only Modal Segues?
If your view controllers have a navigation relationship so using UINavigationController is the way to go:
In 'push' segue, you are basically pushing your ViewController into an
already setup "navigation stack". Well, of course, this is under the
assumption that the ViewController that performs the 'pushing'
operation belongs to the same navigation stack as the ViewController
is pushed into. Generally, you push a ViewController if the pushed
ViewController has some sort of a relationship with the pushing
ViewController. This is very common in applications that has a
NavigationController in its system. A good example for a push segue is
a system where you are displaying a list of contacts. And on tap of a
particular contact, you are pushing a VC that has the corresponding
details of the contact.
Example is real world: list of products => product details => product reviews
If you want to temporary present a view controller and the main focus is your view controller but you need to present another view controller to perform a task like "filter" , "login", adjust "settings" then modal segue is the way to go
In 'modal' segue, there is no stack as such. You are presenting a VC
'modally' over the presentee VC, if that makes sense. This can happen
across any ViewController without any relationship rules. The
presenter should take care of dismissing the VC it presented. A good
example for modal segue is login. On tap of login, you are modally
presenting a VC that has no relationship with the presenter.
If your view controllers are not related to each other, but each view controller has his own navigation stack then UITabBarController is the way to go
Storyboards (Xcode): What is the difference between a push and modal segue?
I would say if each of the additional view controllers from the main "home" view controller don't have any children view controllers, then you can just have each button present a view controller modally.
The main difference is if you are using a navigation controller, you can "pushing" a vc onto the navigation stack of view controllers, whereas presenting it modally can be thought of a "one time" action where the user does something on the new screen and has no where to advance to logically (like adding information to a new contact).
You can see this post for a more detailed answer:
What is the difference between Modal and Push segue in Storyboards?
Deciding whether to use a Modal segue vs a Show (push) depends entirely on purpose and context of the user's experience. If you are leading the user down a path which is linear, where each successive VC is diving deeper in to a singular idea, then use Show segues and NavigationControllers. Examples include, Settings app, where you can drill into all the specifics. Most e-commerce app will use a NavigationController to lead the user through a purchase.
If you want to present the user with a single concept, which the user can respond to, or close it to continue using the rest of the app. Then use a modal presentation. Adding a contact in the iPhone is a fine example of this.
Visually, the difference is that a Show segue presents the VC from the right side of the app, sliding onto the previous VC. (If the user has Arabic language turned on, a right to left language, the Show segue will come from the left hand side of the VC) A modal comes from the bottom of the app.
From looking at your drawing, but not know anything else about your app, I think you want to use NavigationControllers. You may also want to consider a TabBarController. If each of these buttons lead the user on various ways of using the app, like mini apps within one big one, then a TabBarController is appropriate.
I am working working on an app (iOS 5+) that contains a stacks of views that are managed by a navigation controller:
MyNavController -> MyRootViewController -> MyTableViewController -> MyDetailViewController
I also have view controllers that are not managed by the navigation controller for handling the login (LoginViewController) and registration (RegViewController) of the app.
When the app is launched, it will check if an account has been created. If so, it will seque to the LoginViewController for user login, and then it will segue to MyRootViewController. However, if no login is detected, the user will be presented with the RegViewController scene to create an account. Then, I would like to take the user directly to the MyTableViewController scene, bypassing the RootViewController scene. Is this possible (via Storyboard or programatically)? I have attempted to define a modal segue from RegViewController to MyTableViewController, which seems to partially work - it is able to go to the scene but with the nav bar missing on top of screen. But when I select a table item it fails to go to MyDetailViewController. It crashes with error "Push segues can only be used when the source controller is managed by an instance of UINavigationController."
Any advice?
Thanks in advance.
Select your MyDetailViewController. On the top select editor->embed in ->navigation controller.
I want to create an app using storyboard that has login window and tab bar controller.
So the flow will be upon tapping the login button, the app will be redirected to tab bar controller with its views.
I have done this:
But referring to Apple Documentation: UITabBarController
Because the UITabBarController class inherits from the
UIViewController class, tab bar controllers have their own view that
is accessible through the view property. When deploying a tab bar
interface, you must install this view as the root of your window.
Unlike other view controllers, a tab bar interface should never be
installed as a child of another view controller.
So that means I am not allowed to do so?
In addition:
The 3 views that are referred by my tab bar, then each of them has their own child view again, but the tab bar in the child view is gone. What could be happen? Am I missing something?
What I have done in all my apps that are structured similarly is to have the first view controller check for valid authentication and if that fails, present a login VC. That login VC has a delegate defined that will pass back the user credential after a successful login and then dismisses the modal login VC does whatever.
Here is a sample layout:
The delegate protocol looks like this:
#protocol LoginViewControllerDelegate
-(void)finishedLoadingUserInfo:(UserInfo *)curUser;
#end
Where UserInfo is the model I use for the user information (in my case, NetworkID, FullName, etc).
When the user has successfully authenticated, I fire off that delegate method which is handled in the class that presented it. If you need more detail, I can help - but the process is simple.
You can launch your login screen first from the appDelegate and then setup and launch the tabBarViewController after the login is successful.
An alternative design is to do the following steps:
1. set up your tabBarViewController,
2. disable the tabs,
3. launch your login view controller modally,
4. enable tabViewController tabs
Either of these two approaches should work.