Login Logout View Controllers - iphone

I have a Login View where user enters username and password which is working fine to call the next view. Now when the user clicks logout, I am calling the Login viewController using following:
loginViewController *login = [[loginViewController alloc] initWithNibName:#"loginViewController" bundle:nil];
[self presentModalViewController:login animated:YES];
I don't know whether allocation the view again again on logout button action is a good idea.
I am using ARC but I dont know calling the loginViewController will push all the allocated memory of previous viewControllers.
PS:
loginViewController is the root view controler -ie- it is called right after the appDelegate.
I have tried popViewController method of the navigationController but it is not working.
Any other suggestion would be really grateful

As you are using ARC, the objects are managed by the iOS, so once you dismiss the loginViewController it will no longer available in memory. So you for next time you need to allocate & present the loginView again, your code is fine, works good..
I have a sample app made using tabBar with login & logout transitions. Here you can change your rootViewController as per your requirement.

Related

Present Specific Storyboard/View on first app launch

I'm building an app that is going to require a registration on the initial launch of the app. I'm used to using nibs and presenting those but how would I present this view modally and then dismiss it once the registration is complete.
Also would it be better to just have a view in the storyboard or a separate storyboard (I'm assuming the former.)
You'll need to have a separate view in the storyboard (login or registration view). If user is not logged in, you'll show it:
UIViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"YourLoginViewIdentifier"];
[viewController setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:viewController animated:NO completion:nil];
Pretty much the same approach, which you used.

UINavigationController pushViewController stoppes working

I have a problem with the UINavigationController. It about a client or serverside logout.
The idea for serverside logout is this, every 15 seconds a function is called that checks if the App is still logged in. If that is not the case then jump to the LoginViewController.
The Logout can also happen from the App itself. It executs simular code.
There are three relevant Controllers, LoginViewController is where we want to end up, SignOutController is where the 'Sign out'-Button is located and MainViewController.
Here are the relevant code parts.
First, the UINavigationController gets allcated like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
splashScreenViewController_ = [[SplashScreenViewController alloc] initWithNibName:#"SplashScreenViewController" bundle:nil];
uiNav_ = [[UINavigationController alloc] initWithRootViewController:splashScreenViewController_];
uiNav_.navigationBar.barStyle = UIBarStyleBlackTranslucent;
uiNav_.navigationBarHidden = YES;
[window_ setRootViewController:uiNav_];
[window_ makeKeyAndVisible];
return YES;
}
When the 'Sign out'-Button is pressed or the App figures out that the Server has forced a logout, this code is executed (same code, diffrent functions):
LoginViewController *loginView = [[LoginViewController alloc]initWithNibName:#"LoginViewController" bundle:nil];
[self.navigationController pushViewController:loginView animated:YES];
[loginView release];
If its a Serverside Logout it just reloads the MainViewController, every 15 seconds you see the animation of MainViewController sliding in. Its goes in a cycle from there, every 15 seconds it reloads.
If you click the 'Sign out'-Button it jumps to MainViewController instead of LoginViewController and starts the same cycle discribed above.
P.S. I have checked if any importend variable is nil, and I have checked that initalisation code is actually executed.
Edit: I think I did not mention that. My app works 99% of the time. Just one in a while this happen that the Sign-out button does not work and I start this cycle. Normally it works fine.
For the 15 second cycle where a new LoginViewController slides in it just seems you are not stopping to check if the app is logged in after realizing it wasn't. You should have some sort of boolean to store that and cancel the timer or whatever you use.
I don't understand what you say happens when you press the logout button, but I don't think you are making a good user interface.
I suggest you start the application by adding to the navigation controller the loginViewController as root. Then you add without animation the one you want to start with (for example MainViewController). Whenever the application is logged out of the service you pop the view controllers until the first one, which sould be the login one.
You have the method popToRootViewControllerAnimated: for that.
If you want to preserve the splash screen you can set it as the root view controller of the app, and chenge it to the uiNavigationController when you have finished loading.
The timer won't stop automatically just because you've pushed a view on top of another. It will be there until the controller it started on is released, which will only happen after it has been removed from the stack.
Also, you don't need to push MainViewController onto the stack after every check, you'll end up with multiple instances of it, each on top of another.
Also, without really knowing much about the architecture of the app, it would seem like a good idea to make LoginViewController modal, they really can't do anything if they've not logged in right? A modally presented viewcontroller wouldn't be affected by the navigation stack, and would also retain the users navigation stack much easier than having to manually push/pop controllers.

display view controller before tab bar controller

I'm starting my first application for iphone. I'm using xcode 4.3.3, IOS 5, and the principle of storyboard.
the home screen of the application is a tab bar controller and I want to display a login before the home screen if the user does not logged.
I can not find a solution: if I have to use the file AppDelegate.m with the function didFinishLaunchingWithOptions() or file of my controller with the function viewDidAppear() or something else.
if someone would help me for a solution
Thank you.
just create the login screen when your app is launched and when your login is succeed push your tab bar controller from there...
It is better to add function in AppDelegate.m to remove unwanted window appearing if not logged in (Your home view will be shown for a moment before redirecting to login page if you write code in ViewDidAppear method).
Another method is add a new view controller and check where to redirect based on log in status from view controller's ViewDidAppear method.
Try using a Modal View Controller, Docs
On didFinishLaunchingWithOptions() or viewWillAppear() try do something like this:
YourViewController *viewController = [[YourViewController alloc] initWithNibName:#"YourViewController" bundle:nil];
viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
viewController.modalPresentationStyle = UIModalPresentationFormSheet;
//Present as Model view controller
["presentedViewController" presentModalViewController:viewController animated:YES];
//release it After presenting to it
[viewController release];
Then to remove it call: dismissModalViewControllerAnimated: (docs)
you can use another view with login screen and Save Bool value in nsuserdeafault then when app is start check for nsuserdefault and show view according to that.
then after you can call everywhere where you want in delegate.m or viewwillappear.

How to develop a TabBar based application with a login functionality?

I am developing an application where i need to show a list as a menu(Courses,lessons,grade,logout) to the user. so even before this i need to show a login screen. Only upon successful and valid login i need to re-direct the user to the menu. So i have planned to develop a tabBar based application with 4 tabs. Here i am confused on how to add the login view controller even before the TabBar controller is loaded. I want the first tab to be selected every time. As of now i am adding my TabBar controller as a rootviewcontroller to my AppDelegate window and then presenting the login view controller as a modal view controller. But the problem here is even before the Login View controller is loaded, my courses view controller is loaded because the tabbarcontroller is loaded first. My actual requirement is i need to load the course view controller with the list of courses based on the inputs given in the Login View controller. But loadview of course view controller is loaded even before the load view of login view controller. so my list of courses is always the same irrespective of who logs in. I am confused here on how to move forward...Any suggestion here would be of great help...
So, a very quick example, could be; in your loginViewController you should have some method something like this:
//Call this after the user has done with the login
-(IBAction)remove:(id)sender{
AppDelegate *del=(AppDelegate*)[[UIApplication sharedApplication] delegate];
//Set some data based on the user's input (eg some property shared in the AppDelegate)
//del.dataEnterByTheUser=someData;
[del removeLoginView];
}
Then in your AppDelegate (assuming that now the rootViewController is the loginViewController) you could do like this (you can optimize the transition):
-(void)removeLoginView{
UITabBarController *tabVC=[[UITabBarController alloc] init];
ViewController *v1=[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
//v1.data=self.dataEnterByTheUser;
ViewController *v2=[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
NSArray *arrayVC=[NSArray arrayWithObjects:v1,v2, nil];
[tabVC setViewControllers:arrayVC];
[tabVC setSelectedViewController:0];
CGRect rectVC=self.loginViewController.view.frame;
rectVC.origin.y=self.view.frame.size.height;
[UIView animateWithDuration:0.3f delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.loginViewController.view.frame=rectVC;
} completion:^(BOOL finished){
[self.loginViewController.view removeFromSuperview];
self.loginViewController=nil;
self.window.rootViewController=tabVC;
}];
}
Also remember to set in each viewControllers's initWithNibName: the self.title to set the title on the tabItem.
No need to fiddle around with the rootViewController...
Just add the following code at the beginning of your viewWillAppear: method of the view controller which would normally appear first (most likely the VC you are presenting in the first tab):
[self.tabBarController presentModalViewController:loginController animated:NO];
Where loginController is obviously the view controller which manages your login screen. If you show it without animation, it will be the first thing visible when your app launches (after the default image disappears). I've used the same method to show a disclaimer page which the user must read before using the app. It's working just fine and made it to the store without problems.
Edit: In this solution, the loginController must dismiss itself once the user has successfully logged in:
[self dismissModalViewControllerAnimated:NO]; //Although you might do this animated, this time
You can just change the array of view controllers in the tab bar controller at runtime. That should be sufficient for your purposes.
I've written a small example. Try to login with the following credentials:
username: john, password: doe
username: pete, password: poe
You will see a different combination of tabs depending on the login used.
The example can be downloaded from my Dropbox: http://dl.dropbox.com/u/6487838/LoginTabExample.zip

Login to main app

I've already built the main app and the login.
In the appDelegate.m didFinishLaunchingWithOptions, I have
[self.window addSubview:rootController.view];
Which loads up the mainView.
However, I would want it to load up my login first as on a successful login, it will load the rootController (main app) etc.
When I put
[self.validateViewController presentModalViewController:validateViewController animated:YES];
and run the app, all I get is a white screen.
What am I doing wrong?
-> The reason I'm trying to do this is because at the moment, I have the rootController load up first but in the viewDidLoad, it loads the Login modal. Because of that, it runs numberOfRowsInSection first and so when I do eventually go into the app after login, it won't show any tableview since it's already gone through numberOfRowsInSection.
You need to run presentModalViewController on a controller that has a view being displayed already. Right now you are running presentModalViewController on the view you actually want to present.
You could present the validateViewController after adding the rootController to the app window:
[rootViewController presentModalViewController:validateViewController animated:YES];
Just present the login by
[self presentModalViewController:validateViewController animated:YES];