I'm making an application based on TabView Template. In the appdelegate, I've replaced the codes from applicationDidFinishLaunching method, I removed UITabView from it and replaced it with a new View. That view is actually a login screen which appears as soon as the app launches. Now, after successful login, I want the app to switch to UITabView. I tried these codes but they didn't work. :(
Nothing happens when user successfully logs in.
Here's the code I'm using:
NSArray * spanNodes = [bodyNode findChildTags:#"form"];
for (HTMLNode * spanNode in spanNodes) {
if ([[spanNode getAttributeNamed:#"action"] isEqualToString:#"foo"]){
[self.authView.view removeFromSuperview];
[window addSubview:self.tabBarController.view];
[window bringSubviewToFront:self.tabBarController.view]; //Answer to second question
}
}
You don't need to remove the tab bar controller, it's far easier to just leave it in place and push the login screen to be on top of it, covering the tabs until login is successful, as described in an answer to a related question here: Adding login screen in front of Objective C Tab Bar Application for IOS
Related
I have read the apple guidelines and I know it says you shouldn't do that but hear me out as I would like to know if what I am doing is bad practice.
When my application loads up, in the app delegate, a web call is made which sets up the order of the tabs, as well the content within it. Web call is like this
WebCalls *wc = [[WebCalls alloc] init];
[wc setWebCallDidFinish:^(NSString * json) {
// set up tab order here, as well as stores the JSON in a file on the phone
// Also code here to download images and cache them on phone
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
}
[wc getData:phoneNumber];
Now this code works great but the problem is what will happen when app starts is
Launch image shows for a second (which is not very long, sometimes it's half a second or less so just annoying)
Screen goes black for about 2 seconds while json is parsed and images downloaded etc
Then first tab controller is shown
What I want is a seamless transition between the splash screen and the first screen so the user never sees black screen.
What I was thinking of doing is something like this
Change iPhone splash screen time
In the answer given, the guy pushes a view forward to be the splash screen. Would it be bad practice to push that view forward, and then in that screen do the web calls which gets json data, and downloads images, then dismiss the view and have the tabcontroller view become main view?
Or how else would I prevent this delay? Is it bad practice to have a large enough web call like this in AppDelegate?
If this is bad practice to push a view forward while doing background loading, what else would you recommend? Would it be better if I just make the tabController the main rootViewController first and do the webCall in the first tab shown instead, then update the tabs when this web call finished? I was considering this one, but the tab order could be in any order after the web call is made, so not sure what tab will be shown first.
Would be grateful for your input
In the answer given, the guy pushes a view forward to be the splash screen. Would it be bad practice to push that view forward, and then in that screen do the web calls which gets json data, and downloads images, then dismiss the view and have the tabcontroller view become main view?
This is the way to do it. It's generally bad practice to download stuff from applicationDidFinishLaunching, what happens if the phone is not connected to the internet?
Present a simple view controller (using presentModalViewController:controller animated:NO with a UIActivityIndicator and a label describing what's going on, and then dismiss it when loading finishes (or it it fails, just display an error and deny access to the app). Remember to also check for airplane mode and notify the user.
I am designing an iphone application in objective C.
As of now, I have a UINavigationController in the beginning of my application
and rest of the navigation was being handled from it.
Now I want to insert a login screen when the application is loaded.
How do I make it independent of my rest of the application ?
i.e. As of now, I created a LoginViewController and added it to the NavigationViewController
of my app. When the user successfully logs in, the application continues with the next screen being pushed into the Navigation Controller.
But the problem with this approach is that, I can still go back to the initial login screen from the navigation item.
I have tried to hide the navigation bar from the first screen after login, but it removes the navigation bar from each of the subsequent screens.
The only working solution I can think of is that, I should manually hide the navigation bar in the start screen and make it visible in the subsequent screens.
Is there any other sane approach ?
I'd probably do your nav controller disregarding the login screen, and then present the login screen using presentModalViewController:animated:
present your LoginViewController in viewDidLoad for the the navigationController once the user login you dismiss it and continue your screen's flow as you want. also you can store that user login your app in the NSUserDefault so you can check this value and present the loginView in case he didn't login otherwise you show the navigation screen as normal
If the user have not login in the app show LoginViewController and don't allow the user to go to navigation controller till then. Once login don't show LoginViewController directly show navigation controller so that user dont have to sign again and again.. To store user login information use NSUserDefaults. Retrieve the info at loading of the app and display controllers accordingly.
Cheers
You need to store in UserDefaults some value - auto login / did login and when app is start you check this value if user isn`t in system u need to create login view controller and present it modaly.
Before your first view appear u need something like this -
BOOL didLogin = [[NSUserDefaults standardUserDefaults]boolForKey:#"isLogin"];
if (!didLogin) {
LoginViewController *loginVC = [[LoginViewController alloc]init];
[self presentModalViewController:loginVC animated:NO];
}
and when user is login you need to save value in user defaults
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"isLogin"];
if you vant auto login feature you must store password in keychain
I would suggest to hide back button at your firstviewcontroller and unhide in rest all viewcontrollers.
-(void)viewWillAppear:(BOOL)animated {
self.navigationItem.hidesBackButton=YES;
}
Otherwise another solution is that present the loginviewcontroller in the viewDidLoad method of your firstviewcontroller and as login completes dismiss the presented logincontroller on login button.
Even its the standard method to implement, all apps having login facility would have this type of flow.
Hope this will help you out.
In developing my current iPhone application, I'm having issues handling the login, logout functionality of presenting views.
I'd like to have my application have the following flow, but I cannot seem to figure out the proper viewcontroller setup:
When a user is not logged in, a login screen is immediately presented. Upon a successful login, the main application is displayed. The main application is a TabBarController. When returning back to the application, if you have already logged in, the login window will not display, but immediately go into the main tab bar. Once in the app, you can "logout" and it will take you back to the login scren.
Please let me know if I need to go into further detail. There are a few other questions on here that are similar but not exactly what I'm looking for.
Thanks!
I would consider two ways of doing this:
have the login screen be a modal view controller that pops over the main UI.
e.g.
if (currentCredentials == nil) [self presentModalViewController:loginView animated:YES];
or alternately, handle switching between views using your app delegate.
I'm writing an app that will allow iPhone users to login to their accounts. Once logged in the user can pull information, change passwords, change other types of data via webservices. I'm new to iPhone programming and I'm a bit confused on my viewController setup to handle this. What I would like to do is the following;
1) if the user is NOT logged in - display a view which takes up the entire screen displaying my login/password text fields etc. ( I will have some conditionals set in place checking to see if the user has u/p saved in a plist)
2) if user is logged in or once the user logs in, remove the current full size view and load the tabBar view. If the user logs out then the main login view will load.
I will need two viewControllers for this particular scenario? I've read a great deal on view controllers. Read all of the Apple documentation but I still get confused since there are so many options/methods to use.
As always I thank you in advance.
T
Just one of many possible options:
Create LoginViewController and UITabBarViewController. Application delegate will check on start-up whether it already has user's credentials and show the appropriate controller
if ([dataModel hasUserCredentials])
[window addSubview:[tabControlle view]];
else
[window addSubview:[loginController view]];
LoginViewController performs log in and notifies app delegate:
- (void) loginComplete
{
// XXX animation?
// XXX view(Will/Did)(Appear/Dosappear) and all the stuff,
[[loginContoller view] removeFromSuperview];
[window addSubview:[tabController view]];
}
Here is how I would do it:
The tab bar controller is your main view controller. You initialize it first (in the main NIB file) and add it to the window in your app delegate.
In application:didFinishLaunchingWithOptions:, you check whether the user is already logged in or not. If not, you immediately present your login screen as a modal view controller. If you do this without animation, the user will not notice that the tab bar controller is already present underneath.
When the user logs in, you dismiss the modal view controller and your tab bar UI becomes visible.
You should look at creating a Navigation-Based application. This will have a UINavigationController built in. You can use that to control your windows.
I have a window within an iPhone application, which is displayed modally to allow the user to enter their settings for a web service upon 'first run'.
The text fields have helper text set, and when you tap them the keyboard shows and allows you to enter text.
Unfortunately the text fields do not clear the helper text, show the edit caret or show the text being entered (as in the screenshot below).
Any suggestions?
The window is being displayed with [self presentModalViewController:<controller_name> animated:YES];, which may or may not be the cause of this issue - when I run the UI via the Interface Builder 'test' application the text boxes respond like normal.
Clear when editing begins has been set for both fields.
Thanks in advance!
Edited: More information
After the info Bart Gottschalk provided I thought I should add some more information. First, the application is a Navigation Based Application.
Secondly, the test app Bart recommended worked fine, so that takes the modal window and the view out of the equation.
Third, I was presenting the modal view when the -(void)viewWillAppear... delegate method was being called - which may very well be the wrong place... however I'm not 100% sure if I should be presenting the modal view from within the didFinishLaunchingWithOptions of the App Delegate...
(this is happening on Simulator and iPhone 3.1.3)
In Interface Builder did you check the box for "Clear When Editing Begins"? With that checked the text field should clear any value once the use taps to edit which is the behavior I think you're looking for.
You can also set the same property programatically using clearsOnBeginEditing if that is convenient in your code.
My guess is that you've done this and it's not behaving as you expect. Just checking on this as a first step in helping you debug.
Also, does this happen in both the Simulator and on a testing device?
Bart
Edited Below...
This seems strange. Let's strip away everything but the basics of presenting a modal view when the application starts and see what happens.
I've recreated the most basic app (that I know of) to test presenting a modal view controller at launch and verify that field editing works fine. What happens for you when you do the same/similar in a new project?
Here is what I'm doing:
1) Create a new view-based app in Xcode called "ModalViewTest"
2) Create a new UIViewController with xib called ModalViewController
3) In ModalViewController.h add a method
-(IBAction)closeModalView;
4) In ModalViewController.m add the method implementation as
-(IBAction)closeModalView {
[self dismissModalViewControllerAnimated:YES];
}
5) In the ModalViewController.xib create two text fields and set the placeholder text for each to abcd1234 and confirm that "Clear When Editing Begins" is checked.
6) In the ModalViewController.xib add a button "Close" and set Touch Up Inside to fire "closeModalView"
7) In the application delegate (ModalViewTestAppDelegate) add the following import
#import "ModalViewController.h"
8) In the application delegate (ModalViewTestAppDelegate) applicationDidFinishLaunching add the following after the line containing [window makeKeyAndVisible];
ModalViewController *modalViewController = [[ModalViewController alloc] initWithNibName:#"ModalViewController" bundle:nil];
[viewController presentModalViewController:modalViewController animated:YES];
9) Save everything
10) Build and Run this new app
Does editing of the text fields work as expected? If yes, what is different about how you are building and presenting your modalView? If no, then we'll need to dig further to determine what is going on in your environment.
Second Edit Below...
When creating a navigation-based application I did the following to present the modal view at application start. Does this work for you in both your test app as well as your real app?
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
ModalViewController *modalViewController = [[ModalViewController alloc] initWithNibName:#"ModalViewController" bundle:nil];
[navigationController presentModalViewController:modalViewController animated:YES];
}
Well, I just figured it out, but honestly without the persistence and awesome help from Bart it would have taken much longer and been much more frustrating.
It turns out the problem was that I was using a Window instead of a View in the XIB file. This was why when showing the modal view within the Navigation controller it wouldn't display properly (i.e. only a white screen) and why the UITextField would not work properly when showing the view from the RootViewController.
So, to recap - modal views should have UIView, not UIWindow in the XIB/NIB File.
Thanks for your help Bart!
I have the same problem but in iOS7 only. I solved it by changing the tint color of textField to blue in the Storyboard