Dismissing viewController from AppDelegate - ios

I am presenting a tutorial view, from the AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
....
EERootVC *rootVC = (EERootVC *)self.window.rootViewController;
UINavigationController *navcon = (UINavigationController*)rootVC.contentViewController;
EETutorialRootVC *rootTutorialViewController = [rootVC.storyboard instantiateViewControllerWithIdentifier:#"EETutorialRoot"];
[navcon pushViewController:rootTutorialViewController animated:NO];
return YES
}
How can I dismiss this new view once completed?
I've tried this:
[self.navigationController popViewControllerAnimated:YES];
Which works, but the view it returns to seems to be cut off (shifted up?)

Its not going to be self because calling self in AppDelegate is referencing itself (which will be AppDelegate)
If you want to dismiss it from the AppDelegate you simply do the same thing you did to present it:
[rootTutorialViewController popViewControllerAnimated:YES];
But your more than likely not going to dismiss it in the AppDelegate, your more then likely going to dismiss it in the view controllers main class, which is where you would call self

Mmm, it seems you work with some custom setup that you have to provide insight in, so we can give you a better answer.
If you window.rootViewController would be an instance of UINavigationController you'd have pretty default behaviour and if you'd push and pop ViewControllers, everything would look good.
But you are getting the UINavigationController from a custom property of your window.rootViewController. That suggests that EERootVC is some custom ContainerViewController and my bet is something goes wrong in there where you add the EERootVC.contentViewController to it's view and set it's frame.
For example, set the UINavigationController as the Window's rootViewController and I bet it works as supposed too.
Other then that, you push it without animation, and dismiss it with animation. For a good user experience you probably want to think about that approach again.

Related

Change main viewController

I am using multiple viewcontrollers but need to change which who loads first. I have found some old tips but those are regarding .nib files and I belive those might not be up to date. Preferably I'd like to find some option in the menu's, as I frankly think this should be very simple.
Any ideas to a simple way of changing with viewController is loaded first?
Open the storyboard file
Display the document outline
Select the view controller that you want to be first
Under the "Attributes inspector", select "Is Initial View Controller"
You can programmatically load a view controller first through your AppDelegate.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window.rootViewContoller = <firstViewControllerIWantToLaunch>;
return YES;
}
This ensures that the view controller you want to load first is the root view controller, and will be the first view controller presented.
If you're using storyboard, select the view controller you'd like, and search for the "Is initial view controller" checkbox. I can't tell you where exactly it is, since I don't have Xcode open.
If you're using xibs, you need to change it in the AppDelegate applicationDidFinishLaunchingWithOptions method. (Refer to Bryan's answer for that.
If you want to switch between the two view controllers programmatically, Try doing Some thing Like this,
In your AppDelegate.m file in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions.. Method
just place this condition..
If(loadFirstView){
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
FirstViewController *menu = [navController.storyboard instantiateViewControllerWithIdentifier:#"FIrstVC"];
navController.viewControllers = [NSArray arrayWithObjects:menu, nil];
[self.window makeKeyAndVisible];
}else{
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
SecondViewController *menu = [navController.storyboard instantiateViewControllerWithIdentifier:#"SecondVC"];
navController.viewControllers = [NSArray arrayWithObjects:menu, nil];
[self.window makeKeyAndVisible];
}
Don't Forget to assign StoryboardIDentifiers "FirstVC" and "SecondVC" in your storyboard fileā€¦This should do it, It works Well for me
As already answered here, you need to select your project's main storyboard file, select the main view controller, go to attributes inspector and, check the checkbox title "Is Initial View Controller" to make main view controller loading as first view controller upon app launch.

Accessing tableViewController from appDelegate after adding SWRevealViewController

I have an app which displays a simple tableview and I wanted to add the SWRevealViewController as well.
In my appDelegate, before I added the SWReveal VC, I was setting my tableViewController like so...
In didFinishLaunchingWithOptions:
STRTableViewController *tableViewController = [(UINavigationController *)self.window.rootViewController viewControllers][0];
self.delegate = tableViewController;
and then again in the below method:
- (void)loadTableViewData
{
UINavigationController *navVC = (UINavigationController *)self.window.rootViewController;
STRTableViewController *tableVC = navVC.childViewControllers[0];
[tableVC loadTableData]
}
Obviously when I put the SWRevealViewController to the front of the line, this no longer works as it is now trying to call loadTableData from the wrong view controller.
I've tried several ways and keep coming up short. How do I go about accessing the tableViewController now that it is not the first view controller?
If you need more code or logs or anything I'll be happy to post additional info. I have a feeling the answer is right there, I just don't have the experience to see it.
Also, just to be clear, now in the storyboard it goes from Reveal View Controller to Navigation Controller (the tableview's nav VC/ sw_front) and also to the sw_rear VC. Before it simply started with the Navigation Controller.
Thanks!
There's a bunch of ways you can go about keeping a reference to this.
The simplest would be just to keep a reference to the view controller in the AppDelegate.m
So you add a property
#property (nonatomic, strong) STRTableViewController *tableViewController;
Then, whenever and wherever you are instantiating and setting that table view controller, just do something like:
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
delegate.tableViewController = justCreatedTableViewController;
You'll need to #import "AppDelegate.h" to access the app delegate in other classes where you want to do this.
Then to access it you can just do something like:
- (void)loadTableViewData
{
[self.tableViewController loadTableData]
}

UIWindow rootviewcontroller - wrong orientation

I am developing an iPad application where the user just can (in some cases) open the app, if he types in a password.
Therefore I need something like a LoginViewController. But first, let us handle the common case, where the app just needs to display the HomeViewController:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//...
self.controllerHomeView = [[HomeViewController alloc] initWithNibName:#"HomeView" bundle:nil];
self.controllerHomeView.showInitialGuide = isFirstLaunch;
self.window.rootViewController = controllerHomeView;
[self.window makeKeyAndVisible];
//..
}
But, like I said before, some users may have defined a password and if so, we need to display a login screen. That's what I did to enable such a feature:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
//---
if(isAppPinSecured && !loginIsAlreadyDisplaying) {
LoginBackgroundViewController *controllerLoginBG = [[LoginBackgroundViewController alloc] initWithNibName:#"LoginBackgroundView" bundle:nil];
self.appPinInputBG = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default-Landscape#2x~ipad.png"]];
self.appPinInputBG.frame = CGRectMake(0, 0, 1024, 748);
self.appPinInputBG.userInteractionEnabled = YES;
[controllerLoginBG.view addSubview:self.appPinInputBG];
//present new root = background
self.window.rootViewController = controllerLoginBG;
//...
}
}
What I am doing is, changing the root view controller to LoginViewController and if the user puts in the correct password, changing back from the LoginViewController to the HomeViewController.
Everything works fine so far, except the orientation. If the current interface orientation is unknown, because the iPad e.g. is laying on a table, the LoginViewController orientation is LandscapeRight instead of the one in the HomeViewController (LandscapeLeft).
It works properly if holding the iPad in your hands, but otherwise precisely not.
Any suggestions on how to fix that issue? I did set my app orientation in the plist file (Landscape Left). I do implement shouldAutorotate with UIInterfaceOrientationIsLandscape(...) in both - Home- and LoginViewController.
Thanks in advance!
Argh, the problem was, that I tried to push a view controller modally before viewDidAppear was called -> you should never do this...
After changing my code due to this error it worked like a charm
I think what is happening is that the preferred orientation is set on the initial root controller - when you switch it out, it doesn't get set.
I would suggest you consider always making HomeViewController the root controller. And instead of switching the root controller, push the LoginViewController (with no animation if you want it to show up instantly):
[self.navigationController pushViewController:controllerLoginBG animated:NO]
That way you'll be able to do things like logout and pop to the HomeViewController. It will also keep your view controller navigation consistent.

iOS Storyboard Switch to a View that has no segue on AppDelegate

I have a one time agreement view that will only show up when user launches app first time.
I use storyboard IOS 5.1 and My rootview is a navigationviewcontroller. My agreement view has no connection with navigation controoler I just want to present a modalview pop up then dismiss the view:
I use following code but it doesn't do anything app just continues and launches navigationviewcontroller I put flags, yes app enters the if statement. :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if(login==ok){
UIStoryboard *storyboard = [UIApplication sharedApplication].delegate.window.rootViewController.storyboard;
UIViewController *loginController = [storyboard instantiateViewControllerWithIdentifier:#"AgreementViewController"];
[self.window.rootViewController presentModalViewController:loginController animated:YES];
}
return YES;
}
How can I switch a viewcontroller that has no connection to storyboard and dismiss it?
In the app I've been working on last weekend I had a similar situation. I wanted to show a seperate storyboard the first time for a guided setup.
My code looked pretty much the same as yours and it gave me a warning when I was debugging it.
This was because of the fact that the rootViewController I was trying to present my one-time ViewController on, isn't visible at this point in the app.
So, instead of presenting my one-time view controller "on" the rootViewController, I decided to set my one-time view controller as the rootViewController.
In your case it would be something like:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if(login == ok) {
UIStoryboard *storyboard = [UIApplication sharedApplication].delegate.window.rootViewController.storyboard;
UIViewController *loginController = [storyboard instantiateViewControllerWithIdentifier:#"AgreementViewController"];
[self.window setRootViewController:loginController];
}
return YES;
}
To dismiss it, you could probably add a segue from your one-time view controller to your first view controller or you could use code similar to the one in your question.
Another approach would be to do the check and view switching in your first "normal" view's viewDidAppear, instead of in the AppDelegate.
Hopefully this will point you in the right direction.

Navigation Controller is null

I have a split-view app that allows a user to select and display a thumbnail of a chosen image. I have placed a UIButton in the detailViewController using Interface Builder. When this button is pressed, I would like to have it change to a full screen view of the image. I have set up a new View Controller, called FullViewController and thought I had everything connected. The problem is that the navigation controller is null. I adjusted the AppDelegate.m to the following:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after app launch.
// Set the split view controller as the window's root view controller and display.
self.window.rootViewController = self.splitViewController;
UINavigationController *nvcontrol =[[UINavigationController alloc] initWithRootViewController:fullViewController];
[window addSubview:nvcontrol.view];
[self.window makeKeyAndVisible];
return YES;
}
This is the function in the DetailViewController.m which is called when the button is pressed. The navigation controller comes up null in here.
//Function called when button is pressed - should bring up full screen view
- (IBAction) pressFullViewButtonFunction: (id) sender{
//viewLabel.text = #"Full View";
if (fullViewController == nil){
FullViewController *fullViewController = [[FullViewController alloc] initWithNibName:#"FullViewController" bundle:[NSBundle mainBundle]];
NSLog(#"fullViewController is %#", fullViewController);
self.fullViewController = fullViewController;
}
NSLog(#"self.navigationController is %#",self.navigationController);//this is null
[self.navigationController pushViewController:self.fullViewController animated:YES];
}
I'm not sure how to fix this. I've tried adding in the couple lines in the AppDelegate, but when it runs, the table in the root view doesn't show up and it no longer properly switches between portrait and landscape views.
I have the rest of the code readily available if that would help clarify. Just let me know!
Thanks.
From the code you post it is not possible to identify the problem, but two common reasons for self.navigationController to be nil are:
you did not push the object behind self on to the navigation controller in the first place; indeed it seems so, since the navigation controller is added as a subview of the split view controller; possibly you mean the opposite... not sure...
(sub-case of 1) you showed the object behind self using presentViewControllerModally.
When I say "the object behind self" I mean the instance of the class where pressFullViewButtonFunction is defined.
If you need more help, post the code where you push your controllers on to the navigation controller...
On a side note, if you do:
UINavigationController *nvcontrol =[[UINavigationController alloc] initWithRootViewController:fullViewController];
and nvcontrol is not an ivar, then you have a leak.
Hope this helps...

Resources