I want to conditionally display a login screen on launch of an ipad app. I don't want to make it part of a default segue, since they only need to login periodically, not every time.
There are numerous examples of my question, but they all seem to predate ios5. When I use storyboards, however, nothing seems to work.
To reduce this to its essence,
* create a new single view application, using storyboard
* add a new viewcontroller to the storyboard, give it an identifier of "loginScreen"
* put a text label on each view to visually distinguish them.
* in the appDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *storyboard = [self.window.rootViewController storyboard];
UIViewController *loginController = [storyboard instantiateViewControllerWithIdentifier:#"loginScreen"];
[self.window.rootViewController presentModalViewController:loginController animated:TRUE];
return YES;
}
From what I've seen of the examples, that should work. But it still consistently displays the original rootViewController's view. No errors though.
Can anyone point out the (probably small) thing I'm missing?
It turns out that the app isn't in an active state in the didFinishLaunching method.
The proper place to put this is
- (void)applicationDidBecomeActive:(UIApplication *)application
{
UIStoryboard *storyboard = self.window.rootViewController.storyboard;
UIViewController *loginController = [storyboard instantiateViewControllerWithIdentifier:#"loginScreen"];
[self.window.rootViewController presentModalViewController:loginController animated:NO];
}
#deafgreatdane: Your solution would present the view controller modally each time the application becomes active from being in a background state (which may be desirable).
In my case (using this to show a one-time only launch screen) I would add a dispatch_once to that solution to make sure that the modal launch screen will only show up once:
- (void)applicationDidBecomeActive:(UIApplication*)application
{
static dispatch_once_t onceToken;
dispatch_once( &onceToken, ^
{
SomeLaunchViewController* launchViewController = [[SomeLaunchViewController alloc] init];
[self.window.rootViewController presentViewController:launchViewController animated:NO completion:NULL];
} );
}
This code snippet uses ARC.
Related
I have an application that is implementing remote notifications. My desire is to change the initial view controller based on one of three conditions: the user started the app on their own (no notifications); or, the user received an suspicious activity alert; or, the user received a crime alert. I have implemented the application didReceiveRemoteNotification: method in the appDelegate. Based on the notification and the user response to the notification I have implemented the following code:
UITabBarController *tbContr = (UITabBarController*) self.window.rootViewController;
UINavigationController *navContr = [tbContr.viewControllers][2];
ViewCrimesController *viewCrimes = [navContr.storyboard instantiateViewControllerWithIdentifier:#"ViewCrimes"];
[navContr presentViewController:viewCrimes animated:YES completion:nil];
[self.window.makeKeyAndVisible];
The problem I am having is that the navigation controls -- ie, the back button and the navigation bar title; are not on the ViewCrimesController when it is presented. I have tried to load the ViewCrimesController many different ways. Each way I get either and error saying there is no segue (this view is a model view to map view) or I am attempting to load the over an active view or, again, I don't get the navigation controls.
Do I need to specifically program the navigation controls or am I missing something in the way I am attempting to load the view?
I have seen references to dynamically changing the initial view in other posts. But I have not seen anything that indicates specific programming is required to add the controls. Any help you can provide is greatly appreciated!
Susan
Have you looked at the post, Programmatically set the initial view controller using Storyboards
The answer from that post may solve your issue,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *viewController = // determine the initial view controller here and instantiate it with [storyboard instantiateViewControllerWithIdentifier:<storyboard id>];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
return YES;
}
You can also download this sample, and implement it as per your requirement.
simply change the key window's rootViewController, sample code placed here, hope it helps:
UIStoryboard *storyboard = self.window.rootViewController.storyboard;
UIViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:#"rootNavigationController"];
self.window.rootViewController = rootViewController;
I am testing my app on iphone and the software version is 4.2.1. I find some problems happened when switching from a customer launchview controller to the rootview controller. The code is as below:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
....
launchViewController = [[[LaunchImageTransition alloc] initWithNibName:#"LaunchView_iphone" bundle:nil controller:self.viewController animation:UIModalTransitionStyleCrossDissolve] autorelease];
self.window.rootViewController = launchViewController;
....
}
In the "LaunchImageTransition.m":
//do some initial work
[self presentModalViewController:self.rootViewController animated:YES];
The rootViewController is initialed in the "MainWindow.xib".
When I test on the iphone simulator, everything is ok. But when I test on the real device, I find that the viewDidAppear method of the rootViewController is called twice while the viewDidload method is called once. This result in two of the same view。
I want to know why this only happened on real device and how to fix it?
I think that the problem is that you are using the view system in a way that it is not the way it has been thought it should be used. My advice is to change the way you present your views.
I don't know if you have to do this exactly this way, but I think that a better way to go is to let the rootViewController as it should be, like the mainViewController.
At the end of the - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method you can present the launchView as modal on the mainViewController.
[mainViewController presentModalViewController: launchViewController animated:YES];
And on the viewWillAppearMethod or viewDidAppearMethod of the mainViewController you can dismiss the launchViewController.
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self dismissModalViewControllerAnimated:YES];
}
I hope it helps...
I have two views - view1 and view2.
View1 is my default viewcontroller loaded from mainwindow.xib.
Depending on some condition checking, i want to load either View1 or View2, say if user registration is not done, load sign up screen for user, else go to default view controller.
How and where do I check this condition?
Please help.
Thanks in advance.
In your app delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if(needToLogin) {
[self setViewController:[[[ViewController2 alloc] initWithNib:#"Login View"] autorelease]];
}
[window setRootViewController:viewController];
}
This will switch your view controller to the view2 view controller if needToLogin returns true. Otherwise, it will go to the default controller specified in mainwindow.xib
Another method (since you probably need the main view controller anyway) would be to present the login view controller if its needed.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if(needToLogin) {
ViewController2 *loginVC = [[[ViewController2 alloc] initWithNib:#"LoginViewController"] autorelease];
[[self viewController] presentViewController:loginVC animated:NO];
}
[window setRootViewController:viewController];
}
Note, you will have to call [self dismissViewControllerAnimated:YES] to get rid of the login view.
Edit: Respones from OP:
I tried first one,
if(loginflag){
[self setViewController:[[[SignUpViewController alloc] initWithNibName:#"SignUpViewController" bundle:nil] autorelease]];
}
[self.window setRootViewController:self.signUpView];
Try this instead:
if(loginFlag) {
[self setViewController:[[[SignUpViewController alloc] initWithNibName:#"SignUpViewController" bundle:nil] autorelease]];
}
[[self window] setRootViewController:[self viewController]];
If you are just planning on bringing up a sign-up screen if the user registration is needed, why not stick with the default view controller, but at -applicationDidBecomeActive: present a modal view controller for the sign up view?
With the information given, you could just create a flag in the AppDelegate that can be persisted based on the user registration is complete or not. Then in the "didFinishLaunching..." method you could check this flag and load the the proper view based on this.
Creating a new app based on the SplitViewController template and it works fine in Split View.
My main screen is to be a non-splitview 'menu'. I'm trying to figure out the best practice for
adding this 'mainMenu' modally above the splitViewController. (Then either push other non-split views above the mainMenu or
remove it to reveal and use the UISplitViewController.)
I have tried:
[self.navigationController presentModalViewController:mainMenu animated:NO];
And
[self presentModalViewController:mainMenu animated:NO];
In the viewWillAppear and viewWillLoad methods for rootViewController & detailViewController. In both cases, the code executes without error, but the mainMenu doesn't appear, the regular detailViewController and rootViewControllers appear.
(I did create an outlet from the navigationController in the main.xib file to the detailView navigationController, but that didn't change anything.)
I was able to make this work by using, which works, but seems like it is incorrect.
iPad_Prototype_SplitAppDelegate *delegate = (iPad_Prototype_SplitAppDelegate *) [ [UIApplication sharedApplication] delegate];
[delegate.splitViewController.view addSubview:mainMenu.view];
[delegate.splitViewController.view bringSubviewToFront:mainMenu.view];
I've seen many responses saying to present such a covering view modally, but I can't seem to find the right place or configuration in the splitViewController setup. Thanks for any help or insight.
Finally, is this approach wrong, should I just be swapping out the detailViewController and having it take full screen in portrait mode and not add the menu item for the root controller?
Is your splitViewController in the AppDelegate like the example and will this help?
//AppDelegate.m
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
MyController *myCont = [[MyController alloc] initMainMenu];
// mess around with myCont.view.modalPresentationStyle;
[myCont setModalDelegate:self];
// Create a delegate (<ModalControllerDelegate>) to dismiss view when done
[self.splitViewController presentModalViewController:myCont animated:NO];
[myCont release];
}
// for completion sake
-(void)modalViewDismiss:(MyController *)modalView {
[self.splitViewController dismissModalViewController:YES];
}
Hey im trying to display a modal view controller as soon as my tab bar controller app opens.
There is something wrong with the code below, and im 99% sure its the code for this. what do i put for the thing im calling it on?
[self presentModalViewController:promt animated:YES];
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after app launch.
//Displays the password prompt modally
PasswordPromViewController *promt = [[PasswordPromViewController alloc] initWithNibName:#"PasswordPromViewController" bundle:nil];
promt.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:promt animated:YES];
[promt release];
return YES;
}
any ideas would be helful!
Cheers
I'm guessing you're adding this code in the application delegate file (eg if your app is called XXX then XXXAppDelegate.m). If this is the case you cannot use:
[self presentModalViewController:promt animated:YES];
as this method has to be called on an instance of a UIViewController. If you've set up your project in the standard way then your app delegate should have an object called window, which is a reference to the main window of the application. It's probably simplest if you add the modal view controller to that, like so:
[window presentModalViewController:promt animated:YES];