iPhone orientation management : what is the most efficient way to do? - iphone

I need to develop an iPad application which should manage the two orientation mode (landscape and portrait).
According the official Apple iOS documentation, there are 2 ways to proceed.
-The first one consists in adjusting views element when the rotation event is received. The main advantage is that we had only one ViewController
-The second one consists in displaying a specific ViewController for each orientation. Therefore, we have 2 ViewControllers.
The second approach seems to be nice, but I'am afraid by the numbers of ViewController that will be needed. What's more, the "data synchronisation logic" in the ViewControllers will have to be duplicated (or isolated from the ViewController) to be used in both orientation.
The application I need to develop will contain many "full custom elements" and many ViewControllers.
If anyone has advices or experience feedback, it would be really appreciated ;)
Thank's for reading !

The second way should rather be: using 2 different views (one for portrait, one for landscape) and swapping the view controller's view in willRotateToInterfaceOrientation:. No need to duplicate your data logic.
Which way to use? I would say: it depends.
If the lanscape and the portrait modes differ only by the position / size of views, I use the first one (plus you'll get nice animations of the frame changes)
If landscape and portrait are too different, I prefer the second one.

I usually solve this by taking advantage of the autoresizing techniques in the view combined with the implementation of willAutorotateToInterfaceOrientation and willAnimateRotationToInterfaceOrientation methods in the view controller.
With autoresizing techniques you can easily resize standard UI elements provided by Apple. If your UI elements doesn't have an impossible layout, you can apply the autoresizing techniques to them too. You must set the autoresizesSubviews property to YES in the parent view controller and select an autoresizing behaviour for each subview. For example, if you want it to resize to the right maintaining the view centered, you can apply the autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin mask in the subview.
If the autoresizing techniques doesn't do the trick, then you will need to resize each conflicting view separately by implementing the - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration in your view controller. If you have "full custom elements", you will need to resize them this way.
In my particular experience, I prefer to have only one view controller and one view for all orientations and manage them with these two techniques.
Hope this helps you!

Related

How to rearrange views during autorotation in iPad

A view controller has six rectangular views. In landscape mode, I want to arrange them 3 columns and 2 rows. But in portrait mode, I want to arrange them 2 columns and 3 rows.
How do I implement it when iPad rotate between landscape and portrait?
Do I need to have two nib files: one for landscape with 3 columns and 2 rows and the orther for portrait with 2 columns and 3 rows, and swap them during autorotation?
Or something else? What is the best way to implement this? Thanks.
You only need 1 nib file. Create IBOutlets for your columns/rows and then manually set them in:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
You will want to make sure to call willRotateToInterfaceOrientation in your viewWillAppear also to make sure that the initial position of your columns/rows are set correctly when you enter the view in landscape mode.
Perhaps you want to look at UICollectionView. It might work for you. Otherwise, you should look at using autolayout. If you use two nibs you can use UIViewControllers methods such as
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation;
Alternatively, layoutSubviews is called when the device rotates and you could perform any manipulations there.
I think if the differences are fairly minor then you should not need to use two different Nibs.
You can do it with 2 xibs, or if you're using layout constraints, you can set it up in portrait mode (in IB), then in code save those constraints to an array in viewDidLoad. In the willAnimateRotationToInterfaceOrientation:duration: method, create new constraints for the landscape orientation and add them to the superview. Check out my answer to this question, UIView to Ignore Orientation or Stick-To-Bottom Container for an example of how I've done this.,

Best way to show a small view/dialog over an existing screen?

All my views/pages in apps so far have been full screen UIViewControllers that i push and pop from the stack.
I see some apps create a new view/window that appears about the 1/3 the size of the full screen on an iPad, containing tables of items to select or other UI elements. They are commonly used to allow users to filter the current view they were on.
Seeing them in apps, I guess that they are just adding a UIView to there current screen and change its frame depending on where on the screen they want it to appear.
Or am I wrong? Is there another/better way to do this?
I guess you are talking about UIPopovercontroller. There are several tutorials to build the same.check this. Hope that helps you.
It's a little unclear from your question what the view looks like.
If the view is "attached" to a UI element (has a little triangular arrow connecting it to, e.g., a button) and goes away if you tap outside it, then it's a view presented from a UIPopoverController.
If the view overlays everything and dims the content behind it, is likely a model view controller presented with a presentation style of ether page sheet or form sheet.
Both are common and easy to set up. See the class documentation I have linked.
In most cases, these are probably normal modal view controllers whose modalPresentationStyle property is set to either UIModalPresentationPageSheet or UIModalPresentationFormSheet.
Yes you can make your own UIViews and just add them as subviews. Another option for iPads specifically is with the UIPopoverController class.

When in the view reload resources when orientation changes?

I have view that have many subviews, and each have it's own graphics, different for portrait and landscape orientations. When should I load the new graphics when the orientation changes?
If shouldn't be layoutSubviews, I don't also like the idea of reloading resources in view from UIViewController, because of complicated view hierarchy that I have (it would require to pass this information down).
There is also option to register in NSNotificationCenter for orientation changes in each view, and load new resources when it changes. But I don't quite like it either, because I believe that there should be mechanism in iOS that enables that. Or, maybe I should think in a different way, and build different views for portrait and landscape...
What do you suggest?
I would have your subviews all extend a custom view class that has a -setOrientation: method that swaps between the portrait and landscape graphics. Then in your view controller I would override -willRotateToInterfaceOrientation:duration: and add a loop that sets the orientation for all of the children, thereby causing the graphics to swap when the orientation changes.
I think that's the most straighforward way to do it. Using NSNotificationCenter could be tricky and you're left without a guarantee that every child will get the notification.
Anyway, that's how I'd do it. Let me know if you need examples.

How do i make orientation work in my app?

The way my app currently deals with orientation is it repositions all of the items in the view, the layout of which can change as the user interacts with it. I've had numerous problems, such as view's not appearing, views changing before the screen rotates etc. I'm wondering the best way to deal with orientation?
If the landscape-layout is completely different from the portrait-layout I just load all subviews in the init-method of my UIView-subclass and added them as subviews.
The whole magic is done in the layoutSubviews-method where I only check in which orientation I am at that moment. Never call alloc, addSubview, removeFromSuperview, ... methods in layoutSubviews. The layoutSubviews should only contain code that sets the frame-properties of subviews.
Referring to your problems:
view not appearing: maybe forgot an addSubview-call
views changing before the screen rotates: you probably update some frame-properties of subviews outside the layoutSubviews-method
One possibility - if your app only works with one orientation, disallow orientation changes. This is a reasonable response, some apps are only usable in one view.

Structuring iPhone/iPad application views

I have an idea about an application that I want to build and Im new to iPhone/iPad development (but not new to development in other languages/frameworks such as .NET and Java). I want to layout some views on the screen so that they animate (slide in) from different directions into their places.
The question is about the strucuture of the application, if I have say 4 rectanglular areas on the screen that contain business data, such as contacts (name, photo, etc...) and they all take up different widths of the screen (say the first contact takes up one row of the screen, but the next 2 take up half the width of the next row each, and so on).
Should I create a custom view for the different sized contact views, (i.e. LargeCustomView and SmallCustomView, and any other special type that I make) or should it all be one type, say, CustomerDetailsView which could be stretched to fit at design time?
Also, if there were, say, 3 different instances of the same custom view on the one screen, are there 3 instances of the view controller also? Im a little confused about powering the data behind a view, can someone shed some light on this for me? Do I just set the properties (say an instance variable ContactForView) on the view controller for each instance?
Thanks for any help you can give
Cheers,
Mark
Should I create a custom view for the different sized contact views, (i.e. LargeCustomView and SmallCustomView, and any other special type that I make) or should it all be one type, say, CustomerDetailsView which could be stretched to fit at design time?
I think only you can answer that question. If UIView autoresizing masks are enough to accomondate both layouts, you should probably go for just one class. If that's not enough, you can either override layoutSubviews to account for different sizes or perhaps go with a common superclass to contain the logic and two subclasses to do the different layouts.
Also, if there were, say, 3 different instances of the same custom view on the one screen, are there 3 instances of the view controller also?
Because of the way UIViewControllers work, Apple generally recommends not having more than one view controller per screen. From the docs:
You should not use view controllers to manage views that fill only a part of their window—that is, only part of the area defined by the application content rectangle. If you want to have an interface composed of several smaller views, embed them all in a single root view and manage that view with your view controller.
Otherwise, things like device rotation can get tricky as a view controller that is not full screen should probably react differently to such events and Apple's UIViewController is not written to do that. However, nobody stops you from writing your own view controllers (derived from NSObject, not from UIViewController) so that's what I would recommend: if the view is quite complex, write a custom controller class for it but stick to one UIViewController per screen.