13

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 ?

Elgert
  • 470
  • 2
  • 5
  • 19
  • Are u getting any error? – nikhil84 Sep 17 '14 at 13:09
  • nothing, the app just launches normally on its root view controller – Elgert Sep 17 '14 at 13:10
  • Have you tried to set breakpoints and check if is it entering on the second if statement? – jomafer Sep 17 '14 at 13:21
  • From what I see you say that everything is being created programmatically, where do you set your rootViewController if there is no storyboard? – E-Riddie Sep 17 '14 at 15:25
  • There is 1 storyboard that has only the rootViewController and everything else is being created programmatically. No i just found that it does launch the activity but like 10-15 sec late. @jomafer yes it does enter i have NSLogs there but i deleted them when posting here – Elgert Sep 17 '14 at 15:34
  • If you are downloading data from server in sync mode, and you are depending on it's response, the delay is normal (but not user friendly). Anyway I posted an answer how to present and dismiss viewController, if you need more clarification edit your answer or ask another question. :) – E-Riddie Sep 17 '14 at 21:25

6 Answers6

13

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

Community
  • 1
  • 1
E-Riddie
  • 14,660
  • 7
  • 52
  • 74
  • 1
    this way also creates a new navigation controller. The correct way is this `UINavigationController *nav = (UINavigationController *)self.window.rootViewController; [nav pushViewController:listingView animated:YES];` but the problem is the delay and is not the delay of the server cause i can see on the console its 100 ms – Elgert Sep 18 '14 at 10:18
  • If you need to push it, you just push from navigationController which is rootViewController. About delay you said that viewControllers are programmatically being loaded? If you are creating things on viewDidLoad then move them on viewDidAppear, and give me feedback – E-Riddie Sep 18 '14 at 10:38
  • the same, about 7 seconds, its not normal – Elgert Sep 18 '14 at 10:49
  • Remove all the operations and methods you initialize on viewWillAppear, viewDidAppear and viewDidLoad, to see if there is a problem with your viewControllers or the data they are loading – E-Riddie Sep 18 '14 at 10:55
  • 1
    Nevermind i fixed it. I was pushing the ViewController from a background thread instead of the Main thread. Now it launches fast. I feel stupid -_- – Elgert Sep 18 '14 at 11:08
  • I am glad you fixed it! :) – E-Riddie Sep 18 '14 at 11:44
7

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];
yannisalexiou
  • 605
  • 12
  • 25
nikhil84
  • 3,235
  • 4
  • 22
  • 43
  • no StoryBoard, all my ViewControllers are created and pushed programatically – Elgert Sep 17 '14 at 13:16
  • then u should **initWithNib** in ur allocation of ListingViewController. – nikhil84 Sep 17 '14 at 13:17
  • Ok good so u need to re-check ur code as it might not be getting any view to load ,resulting in blank screen(if thats what u getting). – nikhil84 Sep 17 '14 at 13:23
  • I dont get a blank screen, the app just opens normally but not pushing the ViewController, With presentModalView it works but all my project is based on navigationController and i cant navigate thereafter so i cant use `presentModalView` – Elgert Sep 17 '14 at 13:26
  • now it "kind of works". The view controller is opened but this creates a new navigation controller and i dont have the back button I usually have :P – Elgert Sep 17 '14 at 13:36
  • hahaha !!!....still back to the point ,so replace UINavigationController obj with your navigation obj Or add as childVC to rootVC.navigation. Then let me know. – nikhil84 Sep 18 '14 at 03:35
2

Write this code in didFinishingWithLaunchingOptions

  SecViewController *Vc = [[UIStoryboard storyboardWithName:@"Main" bundle:nil]instantiateViewControllerWithIdentifier:@"second"];
   [(UINavigationController *)self.window.rootViewController pushViewController:Vc animated:YES];
Sakshi Singla
  • 531
  • 6
  • 5
1

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()
mike vorisis
  • 2,786
  • 6
  • 40
  • 74
0

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];
jomafer
  • 2,655
  • 1
  • 32
  • 47
0

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;
}
n.by.n
  • 2,458
  • 22
  • 31