Best Practices for more than one UIWindow in an application - iphone

Experts, Please share the best approaches and practices that must be taken care while adding a UIWindow on top of current window.(Window1) I have a situation where I have locked the orientation of a view "A" to Portrait in a view controller. Then I create a new UIWindow and make it as key and visible. The root view controller of this new UIWindow is again a view controller which supports all orientations. The issue I am having is whenever I make the previous window (say window1)as key and visible again, and try to rotate the device,eventhough the view stays locked to specific orientation(say Portrait), the status bar is rotating which looks very wierd.

I think it is a bad idea to rotate a custom alert to an orientation that is not supported by an application. Anyway. To prevent a status bar rotation you should remove your second window
[alertWindow setHidden:YES];
[alertWindow release];
alertWindow=nil;
after disappearence of your alert.
You also might consider usefull this liks:
https://github.com/eaigner/CODialog
https://github.com/gpambrozio/BlockAlertsAnd-ActionSheets
https://github.com/kyoshikawa/ZPopoverController
https://github.com/TomSwift/TSAlertView

Related

UINavigationController with strange behavior

I am developing an application with the following structure,
Each of the three compoenentes has a UINavigationController associated with.
This application is intended to be identical to facebook.
My problem is that in landscape mode, the "POP" actions of navigations have a strange performance, making the animation from the bottom to the top, as if the navigation had not done the rotation, despite the layout being changed to landscape.
I put all the navigation controller with:
[navCenter.navigationBar setAutoresizesSubviews:YES];
[navCenter shouldAutorotateToInterfaceOrientation:YES];
Any idea why this happen?
Thanks in advance.
EDIT:
If i remove my
[self addChildViewController:self.mainConteinar];
The animation works good. But now, the NavigationBars didn't resize.
You should check all your
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
What you describe sounds as if you forgot to return YES for landscape orientation in one of your child view controllers.

Best practices for landscape only apps?

I'm a new iOS programming and I'm developing a simple iPhone game that needs to run in landscape only. I've ...
set supported orientations in the target settings
added the req. plist item (initial interface orientation)
overridden shouldAutorotateToInterfaceOrientation to return YES only for landscape modes
.. and the app "looks" correct, but there are a few odd things going on.
Issue 1 - I'm trying to manually position my views and not rely on autolayout. I've got a UIView in a NIB that I'm loading that needs to be positioned 150px from the right edge of the screen. I have to get the UIViewController's view's height (not width) to correctly position it - like it's not rotated to landscape at this point in the code.
Issue 2 - Implementing a UINavigationController to go from the title screen to the game interaction. When I'm pushing the interaction UIViewController to the stack, it slides in from the right like it's supposed to. When I go back to the title by popping the interaction, it slides UP to the title. It's seems like it's rotating back to portrait?
I think there is something very basic that I'm missing, but I can't find it in my app code. I've gone over the lists for a landscape app but they don't mention more than the list above.
Are there any other things/settings/methods to override that I should be on the look out for?
You need to set shouldAutorotateToInterfaceOrientation in your other viewControllers as well. Especially the ones displayed inside your UINavigationController.
Issue 2:
Don't use many UIViewController's. Use one view controller. Create one main UIViewController and for other UIViewController's just do:
[mainviewcontrl presentModalViewcontroller: child_viewcontrl animated: YES];
For delete a child view controller, use
[child_viewcontrl dismissModalViewControllerAnimated: YES];

How do I remove a view controller from my view hierarchy?

My app has a welcome screen that can only be shown in portrait mode. After the user has tapped through the welcome screen I'd like to show another screen that can be used in both portrait mode and landscape.
I have set up a view controller that implements shouldAutorotateToInterfaceOrientation: returning YES only for UIInterfaceOrientationPortrait, and I add the view to the window with [window addSubView:view]. I tag this view with the tag 1.
When the user taps through the welcome view and the app moves on to the new view I do:
[[window viewWithTag:1] removeFromSuperView];
[window addSubView:myViewController.view];
Where myViewController is an instance of the 2nd view's view controller (that handles the shouldAutorotateToInterfceOrientation method properly).
Now when I rotate, it still calls shouldAutorotateToInterfceOrientation on the original view's view controller, and does not call it on the new view's view controller.
This note from Apple says that only one view controller will get rotation notifications; however, I have removed the other view controller.
What am I doing wrong?
actually that note doesn't say that "only one view controller will get the notifications" but instead it says that "Only the first view controller added to UIWindow will rotate.".
So this might be the problem.
To resolve it, i would say to always have a view added to your window (call it permanent), and add your welcome screen and the next views to this permanent view.
Hope this helps.
as the note you link to state:
Only the first view controller added
to UIWindow will rotate.
So put a flag that makes sure that shouldAutorotateToInterfceOrientation returns NO until the user have dismissed the screen - and then returns YES afterwards. This is a simple and working solution - however, from a code readability point it might be confusing that a "dismissed" view actually controll the rotation.
Personally; my experience is that it's not really worthwhile having some views rotating and some don't - and users tend to don't like it.
happy coding
I wrote up a quick test that shows what you are trying to do should work. Here are the basics I did:
Create two view controllers. App starts with the first view controller being set in the AppDelegate into an instance variable viewController through NIB files. It is then added to the window as you have written.
I then setup an action that when called (could be a Timer, button on first view controller, etc.) that performed the following:
Remove view using [self.viewController removeFromSuperview]. This is different than the way you have done with the tag.
Created second view controller and assigned it to self.viewController.
Added to window like you have specified.
Not sure what is incorrect with your code. I would guess that perhaps the first view wasn't really being removed.

Multiple Windows Rotation Problem - iPhone / iPad

My app uses 2 UIWindows.
The first shown has a TabBar controller with ViewControllers that only rotate to Portrait orientations. Up to here everything woks fine.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (UIInterfaceOrientationIsPortrait(interfaceOrientation));
}
On the other window I have a UIViewController that rotates to all orientations.
The problem is that when I show the second window
[secondWindow makeKeyAndVisible];
And then return to the first one
[firstWindow makeKeyAndVisible];
The statusbar rotates to all directions and the event shouldAutorotateToInterfaceOrientation is not fired. How can i solve the problem?
Its fine to have multiple UIWindows in one app, but the caveat here is that Apple's code seem to check through every UIWindow you have and see if the topmost view controller allows for a certain rotation. If any of those windows allow a rotation your status bar will rotate regardless of whether the UIWindow is frontmost or visible.
In my own app I hide the UIWindow I'm not using, and added a isHidden check in the relevant UIViewControllers to not allow rotation if the window is currently hidden.
Its fine to have multiple UIWindows in one app, but the caveat here is that Apple's code seem to check through every UIWindow you have and see if the topmost view controller allows for a certain rotation.
Per the answer, did many testes and got the conclusion that Status Bar's rotation depends on the top-most view controller of every window.

How to force a screen orientation in specific view controllers?

My application is pretty simple: it starts up with a view controller that holds a table view (in grouped view layout) with a few options. When the user taps on one of the options, I push another view controller onto my navigation controller.
This second view controller simply displays a UIImageView, and the user can change the screen orientation on this view controller between portrait/landscape modes. This works just fine, and all is happy.
However, if the user taps on the "Back" button on my navigation bar while on the landscape mode, the first controller's layout is all messed up. See below for before/after screenshots:
(source: pessoal.org)
(source: pessoal.org)
Any clues on how to force the first view controller (second screenshot in this post) to stay within the portrait screen orientation?
There does not appear to be a way to do this using the documented methods.
I have filed a bug for this: rdar://6399924
"There is no way to always restrict a UIViewController to one orientation"
You can see it on open radar (along with a link to sample code to reproduce the problem) here: http://openradar.appspot.com/radar?id=697
Like someone on the open radar suggested, a workaround is to disable "back" button while in non-portrait:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
// don't let user press "back" button in landscape - otherwise previous view and the rest of the application
// will also be in landscape which we did not feel like testing yet
self.navigationController.navigationBarHidden = (UIInterfaceOrientationPortrait != self.interfaceOrientation);
}
There is a solution to do that : it's to use a view controller and adding its view to the window. then in that controller you force landscape in the shouldAutorotate... methode. It works fine, but be sure it's necessary for your project to use that, because it's not very smart  to force the user to turn his iPhone. By the way, here is an example code if you need it.
http://www.geckogeek.fr/iphone-forcer-le-mode-landscape-ou-portrait-en-cours-dexecution.html
I wasn't able to get this to work the way I wanted. You ought to be able to set a particular orientation for a ViewController, but the NavigationController doesn't seem to always do the right thing.
I ennded up re-designing my screens so that they all work in either orientation. That might be extra work, but it "feels" more natural, anyway.