I'm developing an iPhone app that, amongst other things, allows the user to sign up, log in and logout of a remote web server.
For this piece of app functionality I have 3 view controllers defined.
SignupViewController
LoginViewController
LogoutViewController
and each has a respective xib file.
I want to be able to switch between views based on what button is pressed. For example:
The SignupView will have a signup button and a login button, if the signup button is pressed I want to switch views to the LogoutView and if the login button is pressed then I want to switch views to the LoginView.
Similarly the LoginView will have a login button and when pressed will switch views to the LogoutView
And finallty the LogoutView will have a logout button who's action will switch views to the LoginView
I've been thinking of a number of different strategies to take when developing this but I'm not sure which one is the best.
One idea, and probably the easiest to implement is to have a single view controller with three different views defined in the xib file and to let the controller handle the switching.
I have some issues with this approach, the xib file will be quite large and might be slow to load while my controller logic will likely become very complex.
The second idea and my current approach is to have a parent view controller which is responsible for switching in and out one of the three sub views.
The problem I'm having with this is that button actions can only be assigned to methods in the current sub view controller. In my case the method I need to call to handle the switch is in the parent controller and this method is not available to my sub views.
A delegate would seem the perfect answer here as I could to ask the parent controller to execute the switch method but I'm still unsure as to how I would define a delegate to perform this operation in my code.
Can anyone help with this? Is there a third strategy that would work better than the delegate strategy?
If you use a UINavigationController as your root, then you can pop and push whatever controllers you want. So, you might start something like this:
[rootController.navigationController pushViewController: someVC animated: YES];
Then, later, when you want to switch from someVC to someOtherVC, you'd do this:
UINavigationController *navCon = self.navigationController;
[navCon popViewControllerAnimated: NO]; // get rid of me
[navCon pushViewController: someOtherController animated: YES]; // add new controller.
NOTE: All code typed in browser and untested, but I think you should get the idea from this.
You could use delegates or notifications or other things, but the push/pop thing on the nav controller is really handy for this sort of view-stack rearranging. NOTE: If you don't like the nav controller look, you can hide the nav-bar! :)
Related
I want to move from one UINavigatioController to other UINavigatioController. Scenario is First I am at ContactVC and after pressing any cell I will be move to ChatVC. Now when I press the back button on chatVC I want to move back on InboxVC. How can I achieve this scenario.
A UINavigationController is a stack based navigation system. This means when you navigate forwards you simply add another UIViewController to the stack, and when you navigate backwards you pop a UIViewContrller off the stack.
To do what you are proposing you will need to change the underlying UIViewController's that are currently in the navigation stack. You can do this by using func setViewControllers(_ viewControllers: [UIViewController], animated: Bool) on UINavigationController programatically, but you can't do it through a storyboard as thats not how a UINavigationController is intended to be used.
UINavigationController controller keeps a stack of the views (in simple words to understand) when a push a new view controller onto it. So when you press back it essentially pops the last view controller to display its parent controller. This is also normal user behaviour on the iOS platform.
The behaviour you are looking in counter-intuitive to the user since you are breaking their flow of navigation. But if you can a have a strong case for it. You can manually create a back button which can push to the inbox controller to get this sort of behaviour in code or in interface builder.
Another way to achieve this perhaps what you can see in other apps is:
you have a Signup view controller (which might be the form). When the signup is completed.
change the root view controller of the window to Inbox controller and
The same time, push the Chat controller so when your user pushes the back button, they will be taken back to the Inbox.
So I pretty much built my first app(single view) but i've now decided I should add a little "about/info" button and just give a tiny amount of information on how to use the app and a website to go to.
I wasn't sure about the best way to go about this but storyboards seemed really convenient. A user here answered my question about adding a storyboard to my existing project which seems to work.
Now one question is can I use my current viewcontroller h and m files for the second view (the about screen). I suppose it would technically work if I set the Viewcontroller to the same one as my primary app view.
the only thing this second view is going to have is text and a button to go back. Is it OK to set the connections in the storyboard and just let them use the same Viewcontroller files or is this a big no-no?
Thanks
It is recommended you use a different view controller for each view. In case of a static view controller in which the user doesn't interact with the view except maybe for navigation (which can be handled in the storyboard in many cases), I would just leave that view controller as a generic UIViewController, not a subclass.
Yes you can use the same view controller to control more than one view, however, from what I understand, that doesn't seem like good practice in your case
For instance, if you had similar views with almost identical outlets (say the views have the same UI widgets such as buttons, titles but their layouts vary significantly) you co[uld create a separate view for each different layout and use a single view controller. But from what I understand, in your case, those two views will have different outlets (buttons, labels, etc.)
For this reason, I'd suggest creating a new view controller. Then when you want to show this second view, you will have to present it from your active view controller. I'd highly recommend you read tutorials on view controllers in Apple developer resources. But very quickly, I'd suggest the following
UIViewController *vc2 = [[UIViewController alloc] initWithNibName:#"View2" bundle:[NSBundle mainBundle]]
[self presentViewController:vc2 animated:YES completion:nil];
And to go back to your main view, you'll have to dismiss this second view controller
[self dismissViewControllerAnimated:YES completion:nil];
Of course, they don't have to be animated, you can set them to NO.
I would ask you what are the best practices to make a sign in view on ios.
And only after fetching those text fields, launch the application content.
Does I make two windows ? Apple recommended to use two windows only for external display.
If it is a good practice, how can I build this ?
Thank's in advance.
I would present a modal view controller from the app delegate's application:didFinishLaunchingWithOptions: method
something like
[self.window.rootViewController presentModalViewController:signInViewController animated:NO];
do this after
[self.window makeKeyAndVisible];
then when you are finished with the sign-in view controller you can dismiss it the same as you would any modal view controller
This can be achieved either ways. It depends on your requirement. If you want to use built in navigation for with push effect than you can create two different controller.
This can also be achieved in same controller too. You can create Separate view and will be shown/hidden according to situation. In this case if you want to have animation than you have to write some piece of code for that.
Update
This can be done as follows.
-(void)loadApplication
{
[self.navController pushViewController:tabBarController animated:NO];
}
In MainWindow.xib you take 1 navigation controller and bind it with iboutlet in application delegate. Give your login view controller as its base controller in navigation controller by expanding it.
In MainWindow.xib you take 1 Tabbar controller and bind it with iboutlet in application delegate.
In your Loginview controller have application delegate and on successfull login call loadApplication method accordingly. On failure you can give alert message.
Following screen is to show you how your MainWindow.xib will look like. For instance I have just given LoginViewController at each place in TabBarController. You can take any controller to suit your requirement.
In case of any query please comment. Hope this helps.
I have a number of viewControllers (iPad) that manage different views presenting various screens to the user (start screen -> settings screen -> main screen -> details screen -> summary screen).
Those screens are being traversed sequentially (as arrows above indicate) based on user interaction.One exception to that rule is that I should be able to navigate to start screen from every other screen.
I dont want to allow a user to explicitly navigate through those screens (using navigationbar) - only app logic should do that.
How should I handle such viewControllers presentation logic? Should i use NavigationController with navBar hidden and pop/push viewcontrollers on it? Or is it an unnecessary overkill? Maybe simply adding viewController.view to subviews of root view will be enough?
Sorry if the question is silly but i think i still didint get MVC in iOS quite right
Yep, NavigationController is your friend in this type of scenario. The basics are:
[self.navigationController pushViewController:newViewController animated:YES];
...to add each subsequent view controller on to the stack, and ...
[self.navigationController popToRootViewControllerAnimated:YES];
...to get you back to the start screen.
And it is certainly possible to hide the navigationBar in your viewDidLoad method of each view controller, however this will prevent you from being able to go back in the stack. If that is intentional, then I think it's a perfectly valid set up.
Situation:
I have an Xcode project based on the "Navigation-Based-Application" template. So that means I have a SINGLE UINavigationController that manages a UIViewController.
What I want To Do:
What I want to do is add one more UINavigationController to my project -- and be able to switch back and forth between them. (I want to do this to make space for some seperate unrelated content so that it does not have a back button pointing back to the root view controller.)
Question:
How do I add one more UINavigationController to my project and switch between the two UINavigationControllers?
The most common, and natural iPhone OS, way of doing this is to add a UITabBarController to your application. The Xcode template Tab Bar Application will guide you in the right direction on how to use it.
But...
If you don't like to have a Tab Bar in your application, and wish to switch between different UINavigationController instances (or any UIViewController for that matter), you can do something like this.
First you need to create your UINavigationController instances in a appropriate place (for example a new view controller, or in you Application Delegate, if you want to take the easy way out). You can then switch between controllers by just swapping which Navigation Controller's view that should be visible.
Example in the Application Delegate, "firstNavigationController" and "secondNavigationController" are UINavigationController instance variables:
- (void)showFirstNavigationController {
[secondNavigationController.view removeFromSuperview];
[self.window addSubview:firstNavigationController.view];
}
This will simply display the first instead of the second Navigation Controller. Note that this example is very simple. I didn't take into consideration that you should correctly handle the methods viewWillAppear:, viewDidAppear: and so on.