UIInterfaceOrientation rotation in subview not working - iphone

In my App I use a UITabbarController, which rotates perfectly to all UIInterfaceOrientations in all viewcontrollers. But when I add an UIView to the UIWindow afterwards it will not be added in the current UIInterfaceOrientation, but always in UInterfaceOrientationPortrait (which is default for the app). It won't rotate to a new orientation also. I add the ViewController by using:
LoginViewController *loginViewController = [[LoginViewController alloc] init];
[self.window addSubview:[loginViewController view]];
I have
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
NSLog(#"%#", #"YES IT WILL!");
}
in LoginViewController.m but there will never be logged anything. Any idea why the subview won't rotate?
SideSwipe
EDIT:
Found the solution:
Apparently UIWindow should only have one subview, not more, otherwise things will mess up, so i call:
LoginViewController *loginViewController = [[LoginViewController alloc] init];
[tabBarController presentModalViewController:loginViewController animated:YES];
instead, which will autorotate the loginviewcontrollers view just fine.

I have a view inside another view, when rotation happened, only the parent willRotateToInterfaceOrientation got called, so what I did is add [self.subViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; to parent's willRotateToInterfaceOrientation method.

As you are adding a new subview to window, you have to make the window rotate too.

Related

Correct way to propagate shouldAutorotate into a deep modal viewcontroller in iOS6

What is the correct way to propagate shouldAutorotate into a deep modal viewcontroller in iOS6
Consider the following example:
Create a new sample Tabbed Application in XCode 4.5
In the Summary, select all orientations
Create a new simple UITabBarController, e.g. MyTabBarViewController and add the code
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
In the AppDelegate, replace with UITabBarController by MyTabBarViewController in order to hook the rotation
self.tabBarController = [[MyTabBarViewController alloc] init];
Now the rotation should work, and in the FirstViewController, add the code to show a modal viewcontroller on click
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UIViewController * viewController2 = [[SecondViewController alloc]
initWithNibName:#"SecondViewController_iPhone" bundle:nil];
[self presentViewController: [[UINavigationController alloc]
initWithRootViewController:viewController2]
animated:YES
completion:nil];
}
Problem:
Now since the SecondViewController is wrapped by a UINavigationController, even I have added shouldAutorotate in SecondViewController and can't make the upside down rotation done right.
The only fix is to create a custom UINavigationController and also implement shouldAutorotate and this should work.
But this approach sound stupid and it require me to fix all UI class by implementing the shouldAutorotate and I cannot use shorthands such as [UINavigationController alloc]
initWithRootViewController... anymore, I must implement all these UITabBarController and UINavigationController.
Are there any better approach?
Have you tried this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
It's a notification sent by the device which tell the observer about the rotation. Do not forget to removeObserver when you don't need anymore
That is not stupid, and it's seems to be the right way.
You could create a subclass of UINavigationController, and use
[[MyNavigationController alloc] initWithRootViewController:...].

What notification do I get when a view appears in iphone?

I want to know what notification would I get in my CustomView class when this view will be displayed on screen.
CustomView *customView = [[CustomView alloc] init];
[self.view addSubview:customView];
NewViewController *newController = [[NewViewController alloc] init];
[self.navigationController pushViewController:newController animated:YES];
and after some work I pop this viewController.
[self.navigationController popViewControllerAnimated:YES];
I want to know what method in CustomView class will be called when that view will appear again on the screen.
Actually I have an infinite loop animation in that CustomView and on pushing to nextController I have to stop that animation loop and after coming back I need to start it again.
UIView doesn't get
viewWillAppear
viewDidDisappear
etc
ViewController in which it's contained, however, does, so, in order to pass it to UIView you are to implement following method:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[self.view.subviews objectAtIndex:0] viewWIllAppear]; // i assume your subview is the only one, otherwise you need to know the index, or have it as an ivar/property
}
Another idea - since you use your view a lot, i assume you do not recreate it. Let it be a property of your [[UIApplication sharedApplication] delegate]. Now you can access it like this:
#define SharedView [(appDelegate*)[[UIApplication sharedApplication] delegate] sharedView];
Then make custom UIViewController and overwrite viewWillAppear:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if ( [SharedView.superview isEqual:self.view] )
{
[SharedView viewWillAppear];
}
}
You answered it yourself.
viewWillAppear
Have you looked at: UIView
Observing View-Related Changes
– didAddSubview:
– willRemoveSubview:
– willMoveToSuperview:
– didMoveToSuperview
– willMoveToWindow:
– didMoveToWindow

How to hold NavigationController in subViewController orientation?

I have made a NavigationController structure.
FirstViewController is RootViewController, SecondViewController is a next SubViewController. Each ViewController shouldAutorotateToInterfaceOrientation is a different(refer a following code).
FirstViewController is only portrait available. SecondViewController all support Portrait and landscapeMode.
In FirstViewController after sth button touch, call a pushHandler. next SecondViewController is a pushed.
In SecondViewController after rotated landscape back to the FirstViewController, that orientation is too landscape.
but, I implemented each ViewController orientation different. however each ViewController not independently set orientation. why happen?
How can I viewcontroller each orientation can be set independently, to do?
If SecondViewController change the orientation of the landscapeMode. I want back to the FirstViewController still portraitMode(forever hold portraitState Anything not to be affected).
How do I implements programmatically?
FirstViewController *rootViewController = [FirstViewController alloc] init];
UINavigationController *MyNavigationController = [UINavigationController alloc] initWithRootViewController:rootViewController]];
//FirstViewController
- (void)pushHandler
{
SecondViewController *subViewController = [SecondViewController alloc] init];
[[self navigationController] pushViewController:subViewController animated:YES];
[subViewController release];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
//SecondViewController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
Because you use a UINavigationController for all your UIViewControllers whatever orientation behaviour you will set for the UINavigationController will be applied to all it's children or in otherwords objects on its stack.
Think of a UINavigationController as a house and UIViewControllers as rooms. All the rooms in the house will rotate in the same way the house. There is no way to turn a room without turning the house and other rooms.
But as always there are tricks. Look at my answer to this question Only having one view autorotate in xcode?

presenting a modal view over a splitView

I'm having a problem making a universal app... In the application delegate I set up the main navigation for ipad and iphone:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
window = [[UIWindow alloc] initWithFrame:[ [UIScreen mainScreen] bounds]];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// The device is an iPad running iPhone 3.2 or later.
[self putSplitView];
} else {
[self putTabBar];
}
[window makeKeyAndVisible];
return YES;
}
- (void)putSplitView {
RootiPadViewController *rootiPadViewController = [[RootiPadViewController alloc] init];
UISplitViewController *splitController = [[UISplitViewController alloc] init];
splitController.viewControllers = [NSArray
arrayWithObjects:rootiPadViewController.seccionesView,
rootiPadViewController.noticiasView,
nil];
[window addSubview:splitController.view];
}
- (void)putTabBar {
TabBarController *tabBar = [[TabBarController alloc] init];
[window addSubview:tabBar.view];
}
RootiPadViewController is in charge of loading data an generating the panes for the splitView, so that its initialization incorporates a modalView with a loader, such that:
#implementation RootiPadViewController
#synthesize seccionesView, noticiasView;
- (id)init {
if ((self = [super init])) {
SeccionesVC_iPad *sec = [[SeccionesVC_iPad alloc] init];
NoticiasVC_iPad *not = [[NoticiasVC_iPad alloc] init];
self.noticiasView = not;
self.seccionesView = sec;
Init *initVC = [[Init alloc] init];
[self presentModalViewController:initVC animated:YES];
}
return self;
}
The code compiles without warnings, but for some reason the loadView method of initVC is never called and the modal view doesn't appear...
Any ideas why this might be happening?
thanks for your help!
Antonio
I know this is last year's question, but while I think I found the cause, I'm still trying to figure out a good non-hack solution for dealing with this.
Assuming you're working for iPad:
Upon initialization, splitViewController Master's viewDidLoad is called first, then the Detail's viewDidLoad.
If you attempt to put a modal window initializer in the Master's viewDidLoad, nothing seems to happen: This is because the Detail's viewDidLoad has executed after your modal view's viewDidLoad, resulting in your modal view being hidden away.
Breakpointing the modal view class, I see it enter initWithNibName in the modal view. I don't use ARC and here I assume your modal view doesn't dealloc until the program quits - The modal view is still there, but there's no way to get to it.
In iPhone:
Disregard this - because there is NO splitViewController for the iPhone. In fact, the default Universal splitViewController project treats the Master and Detail view as separate pages. So at application init, all you have to worry about is the Master viewDidLoad.
This is why, in a Universal project, pushing a modal view in viewDidLoad works as intended in the iPhone emulator, but NEVER in the iPad emulator.
Note that this only applies during the viewDidLoad stage; if you push a modal view AFTER viewDidLoad into the Master window, the modal view works as intended.
Maybe you should present your modal ViewController from the RootViewController 'ViewDidLoad' method, instead of the 'init' method... Not sure the view hierarchy is created that soon

How to load subview from the main view?

I am very new to Obj-C and learning iphone development.
My question is how to add subview from app delegate.
Lets say I added subview called "MainView" from "applicationDidFinishLaunching" method.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
MainViewController *aViewController = [[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
self.mainViewController = aViewController;
[aViewController release];
[window addSubview:mainViewController.view];
// Override point for customization after application launch
[window makeKeyAndVisible];
}
"MainView.xib" file has a button to show its child view. When the button is clicked, it calls "showChildView" method.
- (IBAction)showChildView:(id)sender {
if (self.childViewController == nil) {
ChildViewController *childController = [[ChildViewController alloc] initWithNibName:#"ChildView" bundle:nil];
self.childViewController = childController;
[childController release];
}
[self.view insertSubview:childViewController.view atIndex:0];
}
From this code, when app launches, it shows "MainView" with a button. But when I clicked the button, the button is still visible as well as the content from the "ChildView.xib" file too.
How can I hide the "MainView" when I pressed the button and show only the contents of the "ChildView"?
Thanks for your help in advance.
well, you have to remove the original view first, before inserting the new subview, do it this way
- (IBAction)showChildView:(id)sender {
if (self.childViewController == nil) {
ChildViewController *childController = [[ChildViewController alloc] initWithNibName:#"ChildView" bundle:nil];
self.childViewController = childController;
[childController release];
}
[self.mainViewControlle.view removeFromSuperView];
[self.view insertSubview:childViewController.view atIndex:0];
}
Hope this helps.
You might want to check out the Utility App sample -- it demonstrates switching between two views with animation and adding/removing views from parent views.
you might want to create a navigation controller in the main view and than push the childviewcontroller onto it when invoking showChildView. You'll get the back navigation button for free that way