How to perform Segue in AppDelegate? - objective-c

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.

Related

Adding Video as a splash in storyboard ios7

I want to show a video at the beginning of the application start, just like a splash. My whole app will be in Navigation. First, i add the video in a splashViewController and set it in appDelegate as rootView and then simply set the mainViewController as rootView again.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
splashViewController = [[SplashViewController alloc] init];
splashViewController = (SplashViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"SplashViewController"];
self.window.rootViewController = splashViewController;
[NSTimer scheduledTimerWithTimeInterval:9.0 target:self selector:#selector(removeSplashScreen:) userInfo:nil repeats:NO];
return YES;
}
-(void)removeSplashScreen:(id)userInfo
{
[splashViewController removeFromParentViewController];
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
mainViewController = [[MainViewController alloc] init];
mainViewController = (MainViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"MainViewController"];
self.window.rootViewController = mainViewController;
}
Now i want to start navigation from this mainViewController. I use storyBoard & add navigation from Editor > Embed in > Navigation Controller in mainViewController. Don't do it programmatically. But i know the way of implementing it using Nib.xib. Here i also put the arrow(The arrow which indicate the starting VC) mark besides of it. But it getting crash when i click a button from mainVC to go next VC. How can i set the navigation here?
If any one have the answer, please share with me. Thanks a lot in Advance.
The scenario of my storyboard:
happy to help you here in two steps
step 1-
your didFinishLaunchingWithOptions code is almost correct , but it does not matter if its working . so let focus on step two.
step 2- in -(void)removeSplashScreen:(id)userInfo
-first line is good , but you even dont need it because you are going to switch the root controller (leave it for now)
- second line (no need to write it)
- third line is really bad , what you doing here is trying to alloc you mainviewcontroller. really you need it with storyboard? no
- you should load you main view controller from storyboard
MainViewController* mainViewController = (MainViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"MainViewController"];
"this line is enough to load your main view controller from storyboard"
-next line is correct
self.window.rootViewController = mainViewController;
code seems to be working now , but still you are missing navigation controller because you have loaded mainviewcontroller from storyboard, not the navigation controller.
- two solution for it
1- load navigation controller in place of mainviewcontroller(give a storyboard id to navigation controller , load it , and make it as root controller) --i will always go with it
2- make a navigation controller with allocating it & make its rootviewcontroller the mainviewcontroller
-----------------working code ---------------
Ok Despite my advice (in the comments), here is how you can achieve this:
Display splash:
//StoryBoard
UIStoryboard *mainStoryboard = [UIStoryboard
storyboardWithName:#"Main" bundle: nil];
//Splash Controller
SplashViewController *splashViewController = [mainStoryboard
instantiateViewControllerWithIdentifier:#"SplashViewController"];
//Show it
[self.window.rootViewController presentViewController:splashViewController
animated:NO completion:nil];
Remove it:
[self dismissViewControllerAnimated:YES completion:nil];
EDIT: Still not working?
Maybe you called it to quick. do this:
viewDidLoad:
[NSTimer scheduledTimerWithTimeInterval:9.0
target:self
selector:#selector(removeSplashScreen:)
userInfo:nil repeats:NO];
function to remove:
-(void)removeSplashScreen:(id)userInfo
{
[self dismissViewControllerAnimated:YES completion:nil];
}
So the solution, according to pawan's given answer is :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
splashViewController = (SplashViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"SplashViewController"];
self.window.rootViewController = splashViewController;
[NSTimer scheduledTimerWithTimeInterval:9.0 target:self selector:#selector(removeSplashScreen:) userInfo:nil repeats:NO];
return YES;
}
-(void)removeSplashScreen:(id)userInfo
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
mainViewController = [[MainViewController alloc] init];
mainViewController = (MainViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"MainViewController"];
navigationContoller = [[UINavigationController alloc] initWithRootViewController:mainViewController];
self.window.rootViewController = navigationContoller;
}
:)

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 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];

UITabBarController with a UIPopOverController with Multiple Views

I am working on a small app, according to the requirement the app should have a tabBarItem with 3 items. For this I have programmatically created the tabBarController in the AppDelegate.m file and added the 3 different viewControllers, instantiated them and everything is working good. I see the tabBarItems and all views are working. In one of the views lets say in SecondViewController I show a popOverController where I used a UITableView and populate it with items. When I click one of the items it should show another view lets say sendFeedback. Until there everything is working fine, but as soon as this sendFeedback is presented as the modal view, it occupies the whole app i.e it hides the tabBarItem.
I present the important pieces of code here for review:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
viewController1.title = #"First";
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
viewController2.title = #"Second";
UITableViewController *tableView3 = [[tableViewController alloc]initWithNibName:#"tableViewController" bundle:nil];
tableView3.title = #"Third";
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, tableView3 ,nil];
self.tabBarController.delegate = self;
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
[viewController1 release];
[viewController2 release];
[tableView3 release];
return YES;
}
In my popOverViewController.m file I am checking which row is selected in the table according to that I present the view
#pragma mark - TableView Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
sendFeedback *sendEmailViewController = [[sendFeedback alloc]initWithNibName:#"sendFeedback" bundle:nil];
downLoad *downloadFilelViewController = [[downLoad alloc]initWithNibName:#"downLoad" bundle:nil];
if (indexPath.row == 0)
[self presentModalViewController:sendEmailViewController animated:YES];
else
[self presentModalViewController:downloadFilelViewController animated:YES];
}
Can anyone guide me how to overcome this with the multiple views. In case if anyone requires more information from my side I would be glad to provide.
NOTE: It is the same with the other view (downLoad) as well
EDIT: Here is how I am initializing my PopOverController in the AppDelegate.m file
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
if([viewController isKindOfClass:[SecondViewController class]]){
NSInteger index = [[self tabBarController] selectedIndex];
CGRect buttonFrame = [[[[[self tabBarController] tabBar] subviews] objectAtIndex:index+1] frame];
PopOverViewController *popoverView = [PopOverViewController new];
popoverView.contentSizeForViewInPopover = CGSizeMake(250, 85);
popover = [[UIPopoverController alloc]initWithContentViewController:popoverView];
NSLog(#"X:%f Y:%f",buttonFrame.origin.x,buttonFrame.origin.y);
[popover presentPopoverFromRect:buttonFrame inView:self.tabBarController.tabBar permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
Thanks
Modal view controllers are used to "block" your application and fulfill a task before you can proceed. So modal view controllers are not what you want to use.
Instead wrap your controllers which have to be shown in the popover in a navigation controller. In the tableView:didSelectRowAtIndexPath: method you can push the corresponding view controller to the navigation stack.
To slove your problem:
At the place where you create the popovercontroller initialize it with a new UINavigationController. And the navigation controller you have to initialize with a rootviewcontroller namely PopOverViewController.m.
PopOverController *popoverContentController = [[PopOverController alloc] init];
UINavigationController *navcon = [[UINavigationController alloc] initWithRootViewController:popoverContentController];
popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContentController];
And in PopOverController.m
if (indexPath.row == 0)
[self.navigationController pushViewController:sendEmailViewController animated:YES];
else
[self.navigationController pushViewController:downloadFilelViewController animated:YES];