Launching ViewController from AppDelegate - ios

I have a custom URL scheme and i want to open a certain ViewController which is not the root when i go to this URL. I have been able to do that and what remains is pushing this ViewController into the navigationController from the AppDelegate where i handle my URL like this :
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
if ([[url scheme] isEqualToString:#"njoftime"]) {
NSDictionary *getListingResponse = [[NSDictionary alloc]init];
getListingResponse = [Utils getListing:[url query]];;
if ([[getListingResponse objectForKey:#"status"] isEqualToString:#"success"]) {
ListingViewController *listingView = [[ListingViewController alloc]init];
[self.window.rootViewController.navigationController pushViewController:listingView animated:YES];
return YES;
}
but it only launches my app and not the ListingViewController i want to launch.
Any idea how can i do it differently ?

Issue
To deal with pushing and popping the viewControllers from AppDelegate, you need to use [UIApplication sharedApplication] which keeps track to all of viewControllers, beginning with root one.
Solution
To PUSH ViewController from AppDelegate
ListingViewController *listingVC = [[ListingViewController alloc] init];
[(UINavigationController *)self.window.rootViewController pushViewController:listingVC animated:YES];
To POP that ViewController you just presented, you need to use this code
[(UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController popViewControllerAnimated:YES ];

If your using storyboard then you could use below lines for pushing your VC.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
YOURCLASS *obj=[storyboard instantiateViewControllerWithIdentifier:#"YOUR_CLASS_STORYBOARD_ID"];
[self.window.rootViewController.navigationController pushViewController:obj animated:YES];
Update:-
ListingViewController *listingVC = [[ListingViewController alloc] init];
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:listingVC];
[self.window.rootViewController presentViewController:navCon animated:YES completion:nil];

Write this code in didFinishingWithLaunchingOptions
SecViewController *Vc = [[UIStoryboard storyboardWithName:#"Main" bundle:nil]instantiateViewControllerWithIdentifier:#"second"];
[(UINavigationController *)self.window.rootViewController pushViewController:Vc animated:YES];

For Swift 3 version:
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UINavigationController = mainStoryboardIpad.instantiateViewController(withIdentifier: "initial") as! UINavigationController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialViewControlleripad
self.window?.makeKeyAndVisible()

If you want to push a UIViewController, you probably are forgetting to init it with the NibName:
LoginViewController *loginViewController = [[LoginViewController alloc]initWithNibName:#"LoginViewController" bundle:nil];

Your AppDelegate.m should look like this:
#import "TestViewController.h"
#interface AppDelegate ()
#property (strong, nonatomic) TestViewController *viewController;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[TestViewController alloc]init];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}

Related

ViewController lost reference when push notification was being clicked and when the app was in background too

App is in Background
Push notification is received and clicked
App will open and be redirect to the SecondViewController and the back button is clicked
When click to the back button from SecondViewController and back to FirstViewController the "Menu" loss the reference from MenuViewController
Push notification is received and clicked
App will open and be redirect to the SecondViewController and the back button is clicked
When click to the back button from SecondViewController and back to FirstViewController the "Menu" loss the reference from MenuViewController
My Code:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
if (application.applicationState == UIApplicationStateActive) {
.......
} else {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *navigationController=[[UINavigationController alloc] init];
self.window.rootViewController = nil;
self.window.rootViewController = navigationController;
MenuViewController *menuViewController = [storyboard instantiateViewControllerWithIdentifier:#"MenuViewController"];
[navigationController pushViewController:menuViewController animated:NO];
HomeViewController *homeViewController = [storyboard instantiateViewControllerWithIdentifier:#"HomeViewController"];
[navigationController pushViewController:homeViewController animated:NO];
AllNewsNotificationViewController *allNewsNotificationViewController = [storyboard instantiateViewControllerWithIdentifier:#"AllNewsNotificationViewController"];
[navigationController pushViewController:allNewsNotificationViewController animated:YES];
[self.window makeKeyAndVisible];
}
My MenuViewController impl:
#implementation MenuViewController
- (id)init {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
self = [storyboard instantiateViewControllerWithIdentifier:#"MenuViewController"];
if (!self) {
return self;
}
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.homeViewController];
NSDictionary *options = #{
PKRevealControllerRecognizesPanningOnFrontViewKey : #YES,
PKRevealControllerDisablesFrontViewInteractionKey : #NO
};
self.revealController = [SubviewPKRevealViewController revealControllerWithFrontViewController:self.navigationController leftViewController:self options:options];
self.revealController.revealDelegate = self.homeViewController;
// The target view controller must implement this method
self.navBarGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self.homeViewController action:#selector(menuPan:)];
[self.navigationController.navigationBar addGestureRecognizer:self.navBarGesture];
self.view.backgroundColor = [[Configurations sharedInstance] menuBackgroundColor];
_topView.backgroundColor = [[Configurations sharedInstance] navegationbarBackgroundColor];
return self;
}
Menu shortcut (button) from MenuViewController lost the reference and doesn't works.

How to set Root View Controller programatically in Objective C?

I am a newbie in iOS Development trying to learn how to create and set views programmatically.
i am trying to do swift statement in Obj-C
window?.rootViewController = UINavigationController(rootViewController : ViewController())
Project: Single View Application . Trying to link default Created ViewController.h
As per Krunals Answer i updated code but Navigation Controller is not shown in simulator
Cmd+Click on controller does not navigate to ViewController File
#import "AppDelegate.h"
#import "ViewController.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIScreen *screen=[[UIScreen alloc]init];
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.makeKeyAndVisible;
ViewController *controller = [[ViewController alloc] init];
window.rootViewController = [[UINavigationController alloc] initWithRootViewController:controller] ;
Initialise your view controller ViewController before you add (use as root controller of navigation) into navigation controller stack.
Here is sample code to initialise simple view controller
UIViewController *controller = [[UIViewController alloc] init];
Here is sample code to initialise using storyboard
ViewController *controller = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"<ViewController - string identifier of your view controller>"];
Here is sample code to initialise using NIB/Bundle
ViewController *controller = [[ViewController alloc] initWithNibName:#"<ViewController - string NIB name>>" bundle:nil];
According to your code and following comment try this code only (remove other codes from your app delegate launch):
// make sure your NIB name is 'ViewController'
ViewController *controller = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
if (controller != nil) {
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController: controller];
self.window.makeKeyAndVisible;
} else {
//print - your view controller is nil
}
Thanks to Krunal for detailed answer .
Thanks to dan for support
i found issue instead of self.window.rootViewController , i typed window.rootViewController.
setting self.window.rootViewController solved issue.
i dont know difference between self.window.rootViewController and window.rootViewController and reason for issue.
If some one knows answer please provide answer on comment
#import "AppDelegate.h"
#import "ViewController.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UIScreen *screen=[[UIScreen alloc]init];
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.makeKeyAndVisible;
ViewController *controller = [[ViewController alloc] init];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:controller] ;
Delele the file Main.storyboard and let the Main interface option empty before you do it.
And add this code:
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
ViewController *vc = [[ViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
UPDATE: If you want to use storyboard with UINavigationController, try this:
Adding UIViewController and adding with UINavigationController
UIStoryboard *storyboard = self.window.rootViewController.storyboard;
UIViewController *rootViewController= [storyboard instantiateViewControllerWithIdentifier:kIdentifier];
[self setRootViewController:rootViewController];
#pragma mark - Set RootView Controller
-(void)setRootViewController:(UIViewController *)rootViewController {
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
}
UIStoryboard *storyboard = self.window.rootViewController.storyboard;
UIViewController *rootViewController= [storyboard instantiateViewControllerWithIdentifier:kIdentifier];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[self setRootViewController:navController];
-(void)setRootViewController:(UINavigationController *)rootViewController {
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
}

NavigatorController is nil

AppDelegate.m
_viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:_viewController];
nav.navigationBar.barStyle = UIBarStyleBlackOpaque;
[_window addSubview:nav.view];
ViewContoller.m
UINavigationController *nav = self.navController;
[nav pushViewController:controller animated:YES];
I don't know why the UINavigationController always nil.
Please help!!
Instead of adding navigationController's view as window's subview try adding navigationController as window's rootViewController
window.rootViewController = nav;
[_window makeKeyAndVisible];
homeViewController = (mainStoryboard.instantiateViewControllerWithIdentifier("register") as? RegisterViewController)!
let navigationController :UINavigationController = UINavigationController()
navigationController.pushViewController(homeViewController, animated: true)
navigationController.navigationBarHidden = false
window?.rootViewController = nil
window?.rootViewController = navigationController
window?.makeKeyWindow()
#interface AppDelegate ()
#property (strong, nonatomic) UINavigationController *navigationController;
#end
//In Your Appdelegate didfinishlaunching method:
self.window = [[UIWindow alloc] init];
[self.window makeKeyAndVisible];
self.navigationController = [[UINavigationController alloc] initWithRootViewController: YourViewController];
self.window.rootViewController = self.navigationController;
//In Your View controller:
[self.navigationController pushViewController:controller animated:YES];
NEW SOLUTION
try this
in AppDelegate.m
#implementation AppDelegate
{}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UINavigationController *_navController = [[UINavigationController alloc] init];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = _navController;
ViewController* _viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
[_navController pushViewController:_viewController animated:YES];
return YES;
}
in ViewContoller.m now this will work:
UINavigationController *nav = self.navigationController;
[nav pushViewController:controller animated:YES];
OLD SOLUTION
try this code
in AppDelegate.h be sure to have this at least
#interface AppDelegate : NSObject <UIApplicationDelegate>
{}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navController;
#end
in AppDelegate.m at least this
#implementation AppDelegate
{}
#synthesize window=_window;
#synthesize navController=_navController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UINavigationController *_navController = self.window.rootViewController;
UIViewController* _viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
[_navController pushViewController:_viewController animated:YES];
return YES;
}
#end
in storyboard be sure to have created a NavigationController binded to a ViewController, defined as initial view controller and binded as root view controller for the binded view controller
in the app general settings tab be sure to have set the storyboard in the deployment info section (also in this section you could set status bar style)
in ViewContoller.m now this will work:
UINavigationController *nav = self.navigationController;
[nav pushViewController:controller animated:YES];
to edit the navigationBar style you can do it this way
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
}

Login Screen and Navigation controller

So in my App.Delegate I'm doing this -
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.loginViewController = [[LoginViewController alloc] initWithNibName:#"LoginView" bundle:[NSBundle mainBundle]];
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController: self.loginViewController];
self.window.rootViewController = navigation;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
and in my login controller I'm doing this -
- (IBAction)login:(UIButton *)sender {
NSString *username = self.userName.text;
NSString *password = self.password.text;
[AccountUtils emailLogin:username password:password useCookie:true callback:^(NSDictionary *loginResponseJSON){
if([loginResponseJSON count] != 0){
[self performSelectorOnMainThread:#selector(displaySearchController) withObject:nil waitUntilDone:YES];
// [self performSelectorOnMainThread:#selector(switchState) withObject:nil waitUntilDone:YES];
} else {
//incorrect entry info view here.
}
}];
}
- (void) displaySearchController {
SearchViewController *searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchView" bundle:[NSBundle mainBundle]];
UINavigationController *navigator = self.navigationController;
[navigator popViewControllerAnimated: YES];
[navigator pushViewController: searchViewController animated:YES];
}
If I correctly login, I go to the second controller's view, but at the top I'm still allowed to go 'back' to the login page. I don't want that to happen and I thought this case would be taken care off by the popViewControllerAnimated line. How do I make it so that when I login, I am not allowed to go back to the login page?(in other words, I guess pop the login controller off the navigation controller's stack?)
If you want just to remove the loginVC you could set the new navigationController as the rootViewController of the AppDelegate after the user has logged in. So you could move the displaySearchController method in the AppDelegate and call this method (from the loginVC) after the user has logged in:
-(void)displaySearchController{
SearchViewController *searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchView" bundle:[NSBundle mainBundle]];
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController: searchViewController];
self.window.rootViewController=navigation;
}
Otherwise, if you really want the push animation, you can remove the loginVC from the navigationController viewControllers stack in the viewDidAppear of SearchDispalyController:
-(void)viewDidAppear:(BOOL)animated{
NSMutableArray *stackVCs=[self.navigationController.viewControllers mutableCopy];
int idx=[stackVCs indexOfObject:self];
//this remove the previous viewcontroller from the stack
[stackVCs removeObjectAtIndex:idx-1];
self.navigationController.viewControllers=stackVCs;
[super viewDidAppear:animated];
}
Also in the loginVC just before push the searchVC you should call this to hide the back button:
[navigation.navigationItem setHidesBackButton:YES];
You don't want to use a UINavigationController with the LoginViewController and you don't want to push the SearchViewController. Instead, use a UINavigationController with SearchViewController and when you display it, make it the rootViewController.
Do this to achieve what you want.
Move the displaySearchController method to your AppDelegate.m file
Do declare the displaySearchController method in AppDelegate.h file
Now Define the displaySearchController method in AppDelegate.m file as :
- (void) displaySearchController {
SearchViewController *searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchView" bundle:[NSBundle mainBundle]];
UINavigationController *navigator = [[UINavigationController alloc]initWithRootViewController:searchViewController];
self.window.rootViewController = navigator;
}
Call a new local method showNewViewController from your loginController as :
[self performSelectorOnMainThread:#selector(showNewViewController) withObject:nil waitUntilDone:YES];
Now define showNewViewController in your loginController.m file as
-(void)showNewViewController {
AppDelegate *appDele = [UIApplication sharedApplication].delegate;
[appDele displaySearchController];
}
Don't forget to import the AppDelegate.h file to your loginController.m
This will certainly help you.

Error in Switching views due to AppDelegate method

This is what i am doing in my application:
in my appDelegate.m file ,
//Four Views
#synthesize fvc;
#synthesize svc;
#synthesize tvc;
#synthesize pvc;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
NSString *name1,*name2,*name3;
name1 = NSLocalizedString(#"home", nil);
name2 = NSLocalizedString(#"quote", nil);
name3 = NSLocalizedString(#"ship", nil);
UITabBarController *tabBar = [[UITabBarController alloc] init];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
//[application setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
tvc = [storyboard instantiateViewControllerWithIdentifier:#"thirdview"];
fvc = [storyboard instantiateViewControllerWithIdentifier:#"firstview"];
svc = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
pvc =[storyboard instantiateViewControllerWithIdentifier:#"PayViewController"];
fvc.tabBarItem.title = name1;
fvc.tabBarItem.image = [UIImage imageNamed:#"home.png"];
fvc.tabBarItem.titlePositionAdjustment = UIOffsetMake(2.0, 0);
tvc.tabBarItem.title = name2;
tvc.tabBarItem.image = [UIImage imageNamed:#"ping.png"];
tvc.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, 2.0);
svc.tabBarItem.title = name3;
svc.tabBarItem.image = [UIImage imageNamed:#"zoom.png"];
svc.tabBarItem.titlePositionAdjustment = UIOffsetMake(-5.0, 0);
NSLog(#"appdelegate %# and %#",svc,svc.title);
tabBar.viewControllers = [NSArray arrayWithObjects:fvc,svc,tvc,nil];
// the below line does not allow [self.navigationController pushViewController:svNew animated:YES]; to function
self.window.rootViewController = tabBar;
// Override point for customization after application launch.
return YES;
In my fvc view im performing change view operation in okPressed method:
- (IBAction)okPressed:(id)sender {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
SecondViewController *svNew = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
[self.navigationController pushViewController:svNew animated:YES];
}
When i comment the code in the appdelegate method the switching between the views thru the okPressed method is executed successfully. But when I uncomment the appDelegate method it does not perform switching. What i found out was , the code in appdelegate method "self.window.rootViewController = tabBar;" is the culprit. Can anyone guide me on this.
I think you should embed your UITabBarController in a Navigation Controller to make it work:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tabBar];
and then
self.window.rootViewController = navController;
Otherwise you can't push anything since you probably got no UINavigationController to push things to!

Resources