iPad view appears sideways - objective-c

I am working on an iPad app (which will not be submitted to the App Store) which supports only landscape mode.
Most of the views in the application are pushed onto a UINavigationController with a hidden navigation bar.
When I add the following code in the top view controller in the aforementioned UINavigationController, the new UINavigationController (navController) is created in portrait mode and appears sideways and off-screen.
MyViewController *myViewController = [[MyViewController alloc] initWithNibName:#"MyView" bundle:nil];
// viewController.view is landscape in MyView.xib
// myViewController is created in landscape mode
NSLog(#"%#", NSStringFromCGRect(myViewController.view.frame)); // {{0, 0}, {1024, 704}}
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:myViewController];
// navController is created in portrait mode (why?)
NSLog(#"%#", NSStringFromCGRect(navController.view.frame)); // {{0, 0}, {768, 1024}}
[self presentModalViewController:navController animated:YES];
// navController is shifted off-screen after it is presented modally (why?)
NSLog(#"%#", NSStringFromCGRect(navController.view.frame)); // {{1024, 0}, {748, 1024}}
I cannot find any possible reason for this to occur, nor can I figure out how to reorient the view to landscape mode; I can change its frame but its content is still sideways.
I tried adding the following to MyViewController.m to no avail:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return !UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
I even tried adding this code to a UINavigationController subclass which did not work either.

I was able to get the view navigation controller to orient itself correctly by adding it as a subview of my application's root view.
MyRootViewController *myRootViewController = [[[UIApplication sharedApplication] delegate] myRootViewController];
[myRootViewController presentModalViewController:navController animated:YES];
This code is in the top view controller of the navigation controller which is a subview of the root view.

Not sure if this will work, but you could add this key to your Info.plist to indicate what orientation your app supports (at least, this will prevent it from starting in portrait):
UISupportedInterfaceOrientations~ipad => (UIInterfaceOrientationLandscapeLeft, UIInterfaceOrientationLandscapeRight)

Related

load different storyboard views in universal app from button xcode

I am building a Universal iOS app.
I have several buttons on the main view which load other view controllers.
I have set up a "Main.storyboard" and an "iPad storyboard.storyboard".
I have made two views in the "main" and the "iPad".
On the "Main" I have set the Storyboard ID's to "FirstCar" and FirstPlayer".
On the "iPad" I have set them to "FirstCarPad" and FirstPlayerPad".
In the General settings I have designated the app as Universal and set the "Main" as the storyboard for the iPhone and the "iPad" for the iPad.
I am using the following code to launch the view controllers in the storyboards from the initial view.
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
int height = [UIScreen mainScreen].bounds.size.height;
if (height == 568.0) {
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"FirstCar"];
[self presentViewController:vc animated:YES completion:NULL]; }
}
else if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad){
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"ipad storyboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"FirstCarPad"];
[self presentViewController:vc animated:YES completion:NULL]; }
When I tap the first button that accesses the "FirstCar" and "FirstCarPad"
ViewControllers everything works fine but
When I tap the second button that accesses the "FirstPlayer" and "FirstPlayerPad"
viewControllers the app crashes with this
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Storyboard () doesn't contain a view controller with identifier 'FirstPlayerPad''
but I have the viewControllers set up the exact same with the Storyboard ID
I am about to tear my hair out.
Can anybody help me out.
To get this to work I duplicated the Main.storyboard in the finder renaming it Main-iPad.storyboard then added it to the project. I then right clicked on the new storyboard and chose Open Source. This showed the storyboard as code and I changed targetRuntime="iOS.CocoaTouch" to targetRuntime="iOS.CocoaTouch.iPad". I then right clicked it again but chose Open Storyboard.
With the settings set to "Universal" and Main-iPad.storyboard selected as the iPad's storyboard everything works fine. I just have to resize and reposition the elements in each iPad view. Time consuming but worth it.
Hope this can be helpful anybody else. I wish when you reconfigured to iPad from iPhone it resized and repositioned the elements in the views but Oh well.

pushing nil rootViewController onto target <UINavigationController

I've been researching this all day but I haven't found anything about the rootViewController in relation to this error message. I know what the problem is but have no idea how to fix it. My problem is that my window.rootViewController is not connected or shows null and I can't figure out what to do. I've tried everything I could think of in code and in IB, but bad things happen whenever I change something. This is the message I get: "Application tried to push a nil view controller on target UINavigationController"
I can see the window.rootViewController from an NSLog statement:
"window.rootViewController : (null)"
of course, everything was working perfectly before upgrading my Xcode to 4.2 and ios5. :)
btw - the view loads but I cannot work any of the buttons, they do not light up at all. And my navigation works fine too.
here is my appDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[DDLog addLogger:[DDTTYLogger sharedInstance]];
NSLog(#"Viewcontroller : %#", self.viewController);
// Set the view controller as the window's root view controller and display.
//self.window.rootViewController = self.viewController;
//do it this way, previous version not supported in ios5 - may need to check version for compatibility
[self.window addSubview:self.viewController.view];
//set up navigation controller
NSLog(#"window.rootViewController : %#", self.window.rootViewController);
navigationController = [[UINavigationController alloc]
initWithRootViewController:self.window.rootViewController];
navigationController.navigationBarHidden = YES;
NSLog(#"navigationController : %#", navigationController);
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
//force this view to be landscape
[application setStatusBarOrientation: UIInterfaceOrientationLandscapeRight animated:NO];
[self.navigationController.view setTransform: CGAffineTransformMakeRotation(M_PI / 2)];
[self.navigationController.view setFrame:CGRectMake(0, 0, 748, 1024)];
[UIView commitAnimations];
return YES;
}
Thank you.
According to the docs:
Discussion
The root view controller provides the content view of the window. Assigning a view controller to this property (either programmatically or using Interface Builder) installs the view controller’s view as the content view of the window. If the window has an existing view hierarchy, the old views are removed before the new ones are installed.
Double check your nib file to make sure it is connect.
Although the "Application tried to push a nil view controller on target UINavigationController" sounds like you maybe losing your VC reference. How is the property set for this? Is it retained?
Here are the docs.
http://developer.apple.com/library/ios/documentation/uikit/reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html#//apple_ref/doc/uid/TP40006817-CH3-SW33

Presenting a Modal View Controller hides the Navigation Bar

I have a navigation based app with a navigation bar, but there are a few instances where instead of pushing a view controller onto the stack, I need to present the view controller modally. The problem is that when I dismiss the modal view controller, everything functions as expected except that the navigation bar is hidden and the (parent view) has been resized, which is the expected behavior according to the docs. So I figured I could simply call a built-in method to unhide the navigation bar. I have already tried
[self.navigationController setNavigationBarHidden:NO];
as well as the animated version without success.
The documentation talks about this in the method
presentModalViewController: animated:
in the discussion section where it says,
On iPhone and iPod touch devices, the view of modalViewController is always presented full screen" and "Sets the modalViewController property to the specified view controller. Resizes its view and attaches it to the view hierarchy."However, the docs didn't clue me in as to how to undo this process after dismissing a modal view.
Has anyone else experienced this and found a solution?
Edit: I am having this same problem, so instead of asking my own question I am sponsoring a bounty on this one. This is my specific situation:
In my case, I am presenting an Image Picker in a Modal View Controller, over a Navigation Controller:
-(void) chooseImage {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
imagepicker = [[UIImagePickerController alloc] init];
imagepicker.allowsEditing = NO;
imagepicker.delegate = self;
imagepicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagepicker.navigationBar.opaque = true;
imagepicker.wantsFullScreenLayout = NO;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
if (self.view.window != nil) {
popoverController = [[UIPopoverController alloc] initWithContentViewController:imagepicker];
[popoverController presentPopoverFromBarButtonItem:reset permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
} else {}
} else {
[self.navigationController presentModalViewController:imagepicker animated:YES];
}
}
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self.popoverController dismissPopoverAnimated:true];
} else {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
//Save the image
}
-(void) imagePickerControllerDidCancel:(UIImagePickerController *)picker {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self.popoverController dismissPopoverAnimated:true];
} else {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
}
Make sure you a presenting AND dismissing the modalViewController from the UINavigationController, like so:
// show
[self.navigationController presentModalViewController:vc animated:YES];
// dismiss
[self.navigationController dismissModalViewControllerAnimated:YES];
If your view controller is actually on the UINavigationController's stack then this is the correct way to handle the presentation and dismissal of the modal view controller. If your UINavigationBar is still hidden, there is something else funky going on and we would need to see your code to determine what is happening.
Edit
I copied your code into an app of mine and the UIImagePickerController successfully presented and dismissed and my UINavigationController's UINavigationBar was still there. I truly believe that the problem lays elsewhere in your architecture. If you upload a zip w/ an example project I will take a look.
Simply try following code it will work
SettingsViewController *settings = [[SettingsViewController alloc] init];
UINavigationController *navcont = [[UINavigationController alloc] initWithRootViewController:settings];
[self presentModalViewController:navcont animated:YES];
[settings release];
[navcont release];
One need to present the navigation controller in order to have navigation bar on the presented controller
I think I've seen this behavior when presenting a view controller on the wrong VC. Are you calling presentModalViewController on the navigation controller or the individual VC?
Try calling it from the navigationController if you aren't already.
[self.navigationController presentModalViewController:myVC animated:YES];
If you present a controller as model, View controller will appear to total view.
If you want to access the navigation controller properties over the model view, You need to create another navigation controller reference and it continues as previous.
This may be useful for you.
Check this out. This is Apple's Documentation under UIViewController Class Reference:
It clearly mentions that modal view always presents in full screen mode, so it is obvious that navigation bar will be hidden. So put the seperate navigation bar on modal view to navigate back.
presentModalViewController:animated:
Presents a modal view managed by the given view controller to the user.
- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
Parameters
modalViewController
The view controller that manages the modal view.
animated
If YES, animates the view as it’s presented; otherwise, does not.
Discussion
On iPhone and iPod touch devices, the view of modalViewController is always presented full screen. On iPad, the presentation depends on the value in the modalPresentationStyle property.
Sets the modalViewController property to the specified view controller. Resizes its view and attaches it to the view hierarchy. The view is animated according to the transition style specified in the modalTransitionStyle property of the controller in the modalViewController parameter.
Availability
Available in iOS 2.0 and later.
Hope this helps you understand that hiding the whole view along with navigation controller is default behaviour for modal view so try putting a seperate navigation bar in modal view to navigate.
You can check it further on this link
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html
AddContactVC *addController =[self.storyboard instantiateViewControllerWithIdentifier:#"AddContactVC"];
UINavigationController *navigationController = [[UINavigationController alloc]initWithRootViewController:addController];
[self presentViewController:navigationController animated:YES completion: nil];
working for me shows navigation bar
Emphatic and Devin –
As I started reading through the Apple docs to get familiar with the problem, I noticed that the method you're using, presentModalViewController:animated:, appears to be deprecated in favor of presentViewController:animated:completion:. Perhaps you should try to use that method instead.
For your convenience, take a look for yourself:
presentModalViewController:animated: reference
I'll try to put together a quick test program to see whether what I've said above is actually true. But give it a shot – maybe it'll help!
Xcode has a template that does pretty close to what you're doing. from the results, i don't think you should be attempting to perform [self.navigationController presentModalViewController:vc] and [self.navigationController dismissModalViewControllerAnimated:] , but rather simply [self presentModalViewController:] and [self dismissModalViewControllerAnimated:] .
to see how the template does this for yourself, you can use the new project wizard in xcode 4.3 . perhaps it will provide some guidance:
from that choice, choose Next, then give your test project a name, choose "Universal", turn off automatic reference counting, hit next, save where you want it.
now, click on the target and switch the deployment target to 4.3 (or 4.0 if you prefer) for your testing purposes, and switch to your device or the iOS 4.3 simulator .
finally, substitute the following code in applicationDidFinishLaunching:withOptions: in the created AppDelegate.m:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.mainViewController = [[[MainViewController alloc] initWithNibName:#"MainViewController_iPhone"
bundle:nil] autorelease];
} else {
self.mainViewController = [[[MainViewController alloc] initWithNibName:#"MainViewController_iPad"
bundle:nil] autorelease];
}
UINavigationController* navigationController
= [[UINavigationController alloc] initWithRootViewController:self.mainViewController];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
now, when i run this, it doesn't hide the navigationBar. and in the created MainViewController.m from the template, you'll see how it presents the modal view controller and dismisses it from the controller itself and not from the navigation controller. for good measure, to make the template code more like your own, go into MainViewController.m and delete the line that sets the modal view controller transition style ...
(of course, in iOS 5, with storyboards, the same thing can all be accomplished with modal segues ... which is how i've done this for apps that i'm not supporting for pre-5.0 that present a modalViewController in this fashion.)
One of the best solution it to use this Category MaryPopin
https://github.com/Backelite/MaryPopin

Push a view controller in portrait from a view controller that's in landscape

I have a UITableViewController that works in both portrait and landscape. From this controller I push another view controller on to the navigation controller. This new viewController is portrait only.
The problem is that when I am in landscape and push the view controller the new viewcontroller is in landscape as well until I rotate it to portrait. Then it's stuck in portrait as it should be.
Is it possible to always make it appear in portrait? Even if its parent is pushing it in landscape?
Update:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
In viewWillAppear: after statusbar orientation change put this:
//present/dismiss viewcontroller in order to activate rotating.
UIViewController *mVC = [[[UIViewController alloc] init] autorelease];
[self presentModalViewController:mVC animated:NO];
[self dismissModalViewControllerAnimated:NO];
Hopefully it will help!
P.S.Tested on sdk 3.2.5 ios 5.0.1.
In your viewWillAppear: use the following code:
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];

How to load a new view upon orientation change - iOS SDK xcode Interface builder

So I am developing this view based app and I have an app that I want to start in landscape mode (haven't quite worked out how to do that, because in the plist file the "initial device orientation" isn't an option as I am assuming it used to be, from what people have said (I'm new to this app developing thing)).
Anyway I want to switch to a completely new view when I rotate to Portrait, and also a another new view when I rotate to portrait upside down. Up to now I have added View2Viewcontroller.(h+m) into my classes and also View2.xib into my resources.
I have this code:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if((fromInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
(fromInterfaceOrientation == UIInterfaceOrientationLandscapeRight))
{
// Load the view controller I want to display in portrait mode...
}
}
But I'm not too sure how to load the view controller or even where to put this code.
I advise to you use .nibv files, it's better to understand how to initilize view in by code.
anyway there is what you need.
[[viewController alloc] initWithNibName:#"viewController" bundle:[NSBundle mainBundle]];
in code you can do the same without nib filesw by this code
CGRect rect = [[UIScreen mainScreen] bounds];
//create a full-screen window
window = [[UIWindow alloc] initWithFrame:rect];
//create our view controller and add its view to the window
viewController = [ViewController new];
[window addSubview:[viewController view]];
[window makeKeyandVisible];