How to change RootViewController (in AppDelegate) from within CustomViewController? - objective-c

Good day,
My app has authorization form (SigninController) which is loaded in AppDelegate, and after signing in (checking is in SigninController.m) TabBarController should appear (as main view of application).
How can I change controller from Signin to TabBar and where ??
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
SigninController *aSigninController = [[SigninController alloc] initWithNibName:#"SigninView" bundle:nil];
self.currentController = aSigninController;
[aSigninController release];
self.window.rootViewController = self.currentController;
[self.window makeKeyAndVisible];
return YES;
}
SigninController.m
- (IBAction)signinClick
{
........
if (loginOK == YES)
{
//This place is ready to send messages to show TabBar
} else {
UIAlertView *alert = ......
[alert show];
[alert release];
}
}

[appDelegate.window addSubview:appDelegate.tabbarController.view];
[self.view removeFromSuperview];
appDelegate is the application shared delegate.
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];

Related

Programmatically set rootViewcontroller for UINavigationcontroller in Storyboard in Appdelegate

I have a value in NSUserdefaults. I am using storyboard, it is embedded in UINavigationController.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if([[NSUserDefaults standardUserDefaults]objectForKey:#"isLoggedIn"]){
//show home page here
}else{
// show login view
}
}
I can open the app using a URL also
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSString *text = [[url host] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if(text.length > 0){
// show home page
}else {
// show settings page
}
return YES;
}
How can I set the rootViewController for the UINavigationController based on the value that is retrieved .Can anyone please help me out?
You can create an object of UINavigationController with your ViewController as per if/else condition and set the navigation controller as rootViewController property of window in AppDelegate as follows:
LoginViewController *loginController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"loginController"]; //or the homeController
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:loginController];
self.window.rootViewController = navController;
This is what i used in my code
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// Get user preference
NSString * wxyz=[defaults stringForKey:#"wxyz"];
//Get value at wxyz field
if ([self isInValidwxyz:wxyz]) {
//check if wxyz is invalid
//If wxyz is invalid, write custom code
}
else{
//if valid,
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"myStoryBoardiPhone" bundle:nil];
self.window.rootViewController = [storyboard instantiateInitialViewController];
}
else{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"myStoryBoardiPad" bundle:nil];
self.window.rootViewController = [storyboard instantiateInitialViewController];;
}
[self.window makeKeyAndVisible];
}
and then, go through this link for implementation with navigation controller

iOS 6 Preservation and Restoration without Storyboards

I've been trying without any luck to implement state restoration and preservation.
I'm not using storyboards. I have to be doing something wrong.
I set up the restoration identifier for every Nib file.
I know the state is being stored, but never restored properly. The last state shows for half a second and then it goes back to the main view. I've tried many things with no luck. Please help!
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog(#"will finish");
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.viewController = [[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil] autorelease];
navigator = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = navigator;
[self.window makeKeyAndVisible];
[navigator release];
NSLog(#"did finish");
return YES;
}
// As you can see, I started the process of saving and restoring application state.
// Also, I added the restoration identifier for every class that should be restored.
-(BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder
{
NSLog(#"restoring");
return YES;
}
-(BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder
{
return YES;
}
-(void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder
{
NSLog(#"restored");
//navigator = [[UINavigationController alloc] initWithRootViewController:];
isRestored = YES;
}
You should do your controllers initialization in application:willFinishLaunchingWithOptions: because restoration is done before application:didFinishLaunchingWithOptions: is called.
Check this answer.
Also you should programmatically assign restorationIdentifier to all controllers.

How to perform Segue in AppDelegate?

I am trying to complete an application on IOS 5.1 with Storyboard. Basically I am doing a dropbox app. Since I am using Dropbox SDK link to Dropbox is handled in AppDelegate.m. User has the option of be able to unlink from a session and link again in different View Controllers. So every time user link and unlinked app has to switch view from Appdelegate to a view controller that is unconnected to rootviewcontroller
In original Dropbox's example Dropbox handled transition like following code
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
[navigationController pushViewController:rootViewController.photoViewController animated:YES];
}
return YES;
}
return NO;
}
But I am using Storyboard with Navigation Controller and any of the following methods are not working I put methods in comments.
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
NSLog(#"App linked successfully!");
// At this point you can start making API calls
/*UIViewController *viewController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:NULL] instantiateViewControllerWithIdentifier:#"MeetingViewController"];
[self.navigationController pushViewController:viewController animated:YES]; */
//[self performSegueWithIdentifier:#"xxxx" sender:self];
/* LoginDropboxViewController *loginController=[[LoginDropboxViewController alloc] initWithNibName:#"LoginDropbox" bundle:nil];
[navigationController pushViewController:loginController animated:YES]; */
}
return YES;
}
// Add whatever other url handling code your app requires here
return NO;
}
Here is the storyboard of the app
So how can I switch view in AppDelegate.h ?
Note: If I add a segue and name the segue lets say goToMeeting
[self performSegueWithIdentifier:#"goToMeeting" sender:self];
error I get is : No Visible #interface for 'AppDelegate' declares the selector performSegueWithIdentifier:sender
If you consider pushing view manually rather then segueperform following code most probably will work for you
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
NSLog(#"App linked successfully!");
// At this point you can start making API calls
//push view manually
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
LoginDropboxViewController *ivc = [storyboard instantiateViewControllerWithIdentifier:#"LoginDropbox"];
[(UINavigationController*)self.window.rootViewController pushViewController:ivc animated:NO];
}
return YES;
}
// Add whatever other url handling code your app requires here
return NO;
}
You can do it like this:
UINavigationController *navigationController = (UINavigationController*) self.window.rootViewController;
[[[navigationController viewControllers] objectAtIndex:0] performSegueWithIdentifier:#"goToMeeting" sender:self];
This will only work if the index in viewControllers array matches the one of your view controller and if it exists of course. In this case is the first one (in the array and storyboard).
The segue ("goToMeeting") must not be attached to an action. The way you do this is by control-dragging from the file owner icon at the bottom of the storyboard scene to the destination scene. A popup will appear that will ask for an option in “Manual Segue”; pick “Push” as the type. Tap on the little square and make sure you’re in the Attributes Inspector. Give it an identifier which you will use to refer to it in code.
In my case i need to go to dashboard screen from appdelegate using segue, the code as below in objective c.
if([rememberMe isEqualToString:#"YES"]){
//Goto Dashboard
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SWRevealViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"revealVc"];
self.window.rootViewController = vc;
[self.window.rootViewController performSegueWithIdentifier:#"sw_front" sender:self];
[self.window makeKeyAndVisible];
}else{
//Goto login
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
LoginViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
Write inside your didFinishLaunchingWithOptions
Hope it helps some one.

ios remove tabbar on button touch

I've a tab bar based project created and added a login view prior to tab view like this.
AppDelgate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
loginView = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
loginView.delegate = self;
[window addSubview:loginView.view];
[self.window makeKeyAndVisible];
return YES;
}
-(void) loginViewControllerDidFinish:(LoginViewController *) loginViewController{
[window addSubview:tabBarController.view];
}
I'm calling loginViewControllerDidFinish: after authentication in LoginViewController as
[self.delegate loginViewControllerDidFinish:self];
Now in one of the tabs i've added logout button and want to come back to loginView on touch.
-(IBAction) logout:(id)sender{
NMSAppDelegate *appDelegate = (NMSAppDelegate *)[[UIApplication sharedApplication] delegate];
//[appDelegate.tabBarController release];
[appDelegate.tabBarController.view removeFromSuperview];
}
it shows the loginView after calling the above method but after re-login it shows all the previous data and previously selected tab but i want it to be afresh from the first tab.Is there anyway to completely delete the tabbar on logout.so that i'm starting the new session.
Thanks
Cant you create another instance of appDelegate.tabBarController ?
Something like this:
appDelegate.tabBarController = [[UITabBarController alloc] init];
appDelegate.tabBarController.viewControllers = [NSArray arrayWithObject:VIEW_CONTROLLER1, VIEW_CONTROLLER2,nil];
appDelegate.window.rootViewController = tabBarController;
[appDelegate.window makeKeyAndVisible];

Can I use pushViewController with UISegmentedControl?

I want to use pushViewController with UIsegmentedController to push to other view and xib.
Can I do that in xcode 4 ??? If I can , Could you guide me please ?
Here is some code that I try.But won't work.
-(IBAction) segmentedControlIndexChanged:(id)sender
{
if ([sender selectedSegmentIndex] == 0)
{
BDshelveController *shelve_page = [[BDshelveController alloc] initWithNibName: #"BDshelveController" bundle:nil];
}
else if([sender selectedSegmentIndex] == 2)
{
BDlibraryController *lib_page = [[BDlibraryController alloc] initWithNibName:#"BDlibraryController" bundle:nil];
[self.navigationController pushViewController:lib_page animated:YES];
}
}
yes you can, these are the things you could check
you missed segmentedIndex=1 in your code.
you missed to call pushViewController when selected segment=0
Or it is more likely that self.NavigatonController is nil
Your segmented control has not been connected valuechange to your action
If self.navigationController is nil, it depends on how you initialize your app, if your app is navigation bar driven, then this code in your AppDelegate should resolve the issue:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:yourRootViewController]; // <-- depends if you have storyboards, xib etc...you should this already initialized
[self.window addSubview:navController.view];
[navController release]; // <-- depends if you have ARC
[self.window makeKeyAndVisible];
return YES;
}
Otherwise I suppose you can initialize it where you are, by giving self as root controller.
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self];