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

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

Related

Really Stuck on Screen Rotation iOS 6, I Need a xib locked to portrait

Having read every method of handling screen rotation in IOS 6 on here, Apple documents, and fierce Googling, after days and days I am still stuck on this when using xibs.
What im trying to achieve is have a few iPad only xibs, in landscape only, rest of app is portrait.
If I was using storyboards I understand how to subclass the nav controller to override the rotation but I am NOT, im using xibs and would appreciate any input how this works with xibs
In my app delegate:
ICHomeController *homeController = [[ICHomeController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:homeController];
navController.navigationBarHidden = YES;
navController.navigationBar.barStyle = UIBarStyleBlackOpaque;
navController.navigationBar.tintColor = [UIColor grayColor];
self.navigationController = navController;
[self.window setRootViewController:self.navigationController];
[self.window makeKeyAndVisible];
return YES;
In addition to trying what seems like every solution on here Ive tried the obvious in my vew controllers, but as I understand in iOS 6 it doesn't get called.
// Older versions of iOS (deprecated)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeLeft;
}
I've been battling with this for days too with a more complex navigation structure.
The basic rule seems to be that the ROOT controller, whether it be a UINavigationController, UITabBarController or just a simple UIViewController, takes control of the rotation. So as you PUSH UIViewControllers onto the stack, the very first one still controls the rotation.
If you use a modal view, then this model view will be considered the ROOT of the stack until it is dismissed. So if you show a modal UIViewController then push views on top of it, the UIViewController that was presented as the modal view is in control of the rotation.
Just make sure for modal views to use presentViewController:animated:completion.
The easiest way to get certain views to be in a different rotation, is present it modally.
If this can't be avoided, then go right back to your first view or nag controller and set the rotations.
Add some NSLog(#"%s", __FUNCTION__); statements to your rotation methods to see which ones are being called.
In your code above, only the first method is the old iOS5 (Now deprecated) method. The other 3 are the new iOS 6 methods.
Using your example code above, you would need to subclass the UINavigationController. To do this create a new class as a UINavigationController subclass with a different name eg. MyNavigationController and add the rotation methods to it. Then in your code above instead of using
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:homeController];
You would use:
MyNavigationController *navController = [[MyNavigationController alloc] initWithRootViewController:homeController];
Also, make sure you have allowed orientations selected here:
I had the same problem. Here's what worked for me in 5 and 6.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0)
{
return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0) {
return UIInterfaceOrientationLandscapeLeft;
}
In terms of the target summary, only portrait mode is "supported".

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

iPad view appears sideways

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)

Connecting ipad to external monitor

I am trying to connect my ipad app to an external screen using the following (not checking the correct resolution for now - just want it up and running).
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[window addSubview:[navigationController view]];
if ([[UIScreen screens] count] > 1) {
window.screen = [[UIScreen screens] objectAtIndex:1];
}
[window makeKeyAndVisible];
return YES;
}
Is this supposed to redirect everything to the external monitor? How dows it work with touches/gestures? I see in the Apple apps, the controls etc are left on the ipad screen...
You need to have a separate UIWindow instance for each screen you are displaying onto (iPad, external monitor, etc.). Rather than simply set your main UIWindow's screen to the external display, you'll want to create a distinct UIWindow for that display and possibly move your views from the iPad window to the external display window. Otherwise, you won't be able to receive touch input on the iPad screen for controlling what's displayed remotely.
For example, the following code will create a new window on an external display (with externalScreen being the appropriate UIScreen instance):
CGRect externalBounds = [externalScreen bounds];
externalWindow = [[UIWindow alloc] initWithFrame:externalBounds];
UIView *backgroundView = [[UIView alloc] initWithFrame:externalBounds];
backgroundView.backgroundColor = [UIColor whiteColor];
[externalWindow addSubview:backgroundView];
[backgroundView release];
externalWindow.screen = externalScreen;
[externalWindow makeKeyAndVisible];
You will also want to watch for screen connection / disconnection events in your application, and deal with them appropriately. To do this, listen for the UIScreenDidConnectNotification and the UIScreenDidDisconnectNotification.
I have a crude example of this working within the latest code of my Molecules iPhone / iPad application, if you want to see one way of handing the external display.

Multiple MPMoviePlayerViewController fullscreen movie init & switching issue - Fullscreen View doesn't autorotate and minor similar issues

This is my first post at SO. I would like to thank all of the SO users, their contribution have helped me a lot in all of my projects. I am new to the iPhone Application development scene.
Aim of the project is to have a custom interactive User Interface (UI) on top of Movie Player objects (*.mov files on device). The underlying FullScreen MoviePlayers can be more than one and need to switch to different ones based on user Interaction.
I am using cocos2D to achieve the custom interactive UI and effects (for e.g. particle effects on swipe gesture). And I am using Multiple MPMoviePlayerViewController* to play the resident movie files (*.mov) on fullscreen mode (refered to MoviePlayer sample).
Requirement is to switch between movies by switching between default and alternate moviePlayer upon touch detection. Also, the switching should be as smooth as possible.
To achieve smooth switching I am using two moviePlayerViewControllers, each a subview of UIView object in AppController.
Problem a: I am not sure if this is the right way to achieve movie switching.
Problem b: In my current solution. The Default MoviePlayer is rotated in portrait mode, and sometimes the moviePlayer object is not visible. The behaviour is not consistent.
Problem c: The Alternate movie player (object of MPMoviePlayerViewController and added first as subview of UIWindow) rotates on device rotation and behaves properly the Default Movie Player (object of MPMoviePlayerViewController added after) doesn't. Can't think of logical explanation of it. Somewhere I read that MPMoviePlayerViewController creates it's own window and that might be an issue.
// From AppController.h
UIWindow *window; // Parent application window
UIView *viewCocos2D; // Cocos View
UIView *viewMovie; // Default MoviePlayer View
UIView *viewMovieAlternate; // Alternate MoviePlayer View
// From AppController.m
// From DidAppFinishLoading
{
...
// Init the window
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Init the views (Cocos2d, MOviePlayer and AlternateMOviePlayer)
viewCocos2D = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
viewMovie = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
viewMovieAlternate = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// cocos2d will inherit these values
[viewCocos2D setUserInteractionEnabled:YES];
[viewCocos2D setMultipleTouchEnabled:YES];
// create OpenGL view and attach it to a window
//[[[UIApplication sharedApplication] keyWindow] addSubview:window];
[[CCDirector sharedDirector] attachInView:viewCocos2D];
// Default texture format for PNG/BMP/TIFF/JPEG/GIF images
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
// Create a
customMoviePlayerWithUI = [[CustomMoviePlayerWithUI alloc] initWithSuperView:window andMovieView:viewMovie andAlternateView:viewMovieAlternate andSelf:self];
CCScene *scene = [CCScene node];
CocosCustomLayer *cocosLayer = [customMoviePlayerWithUI cocosLayer];
[window addSubview:viewMovieAlternate];
[window addSubview:viewMovie];
// somehow this order lets cocos2D receive the touch events
[window addSubview:viewCocos2D];
[scene addChild: cocosLayer];
[window makeKeyAndVisible];
[[CCDirector sharedDirector] runWithScene: scene];
[UIAccelerometer sharedAccelerometer].delegate = self;
[customMoviePlayerWithUI start];
[self didRotate:nil];
...
}
So the View hierarchy is
Alternate Movie Player View is at bottom
Default Movie Player view is next
Cocos2D Layer View is on top -- Cocos2D view also receives all of the events.
// From CustomMoviePlayerWithUI.h
MPMoviePlayerViewController *moviePlayerView;
MPMoviePlayerViewController *moviePlayerViewAlternate;
// These delegates are used frequently to invoke some functions
AppController* delegateApplication;
UIView *delegateSuperWindow; // Window which contains everything -
UIView *delegateView; // View containing default MoviePlayer
UIView *delegateViewAlternate;// View containing alternate MoviePlayer
Following is the moviePlayerViewController init code -- basically it allocs and inits two moviePlayerViewController objects and adds them as subview to the Default and Alternate UIView objects from AppController
// From customMoviePlayer.m
// initAndPlayMovie is called from the init of CustomMoviePlayer
- (void)initAndPlayMovie:(UIView *)view andAlternateView:(UIView*) viewMovieAlternate
{
// Initialize a movie player object with the specified URL
moviePlayerView = [[MPMoviePlayerViewController alloc] init];
moviePlayerViewAlternate = [[MPMoviePlayerViewController alloc] init];
[moviePlayerView shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft];
[moviePlayerViewAlternate shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft];
//if (moviePlayer)
if (moviePlayerView && moviePlayerViewAlternate)
{
[[[moviePlayerView moviePlayer] backgroundView] setBackgroundColor:[UIColor blueColor]];
[[[moviePlayerViewAlternate moviePlayer] backgroundView] setBackgroundColor:[UIColor redColor]];
//[moviePlayerView setWantsFullScreenLayout:YES];
// private API call.. don't use it..
//[mp setOrientation:UIDeviceOrientationPortrait animated:NO];
[view addSubview:[moviePlayerView view]];
[viewMovieAlternate addSubview:[moviePlayerViewAlternate view]];
//[view bringSubviewToFront:[moviePlayerView view]];
//[[moviePlayerView moviePlayer] play];
}
}
Thanks for all of your help. Let me know if you need any more details on it.