iphone landscape mode slow - iphone

The iphone app I am developing in landscape mode is seriously chugging. I put it in portrait for comparison and it appears to run much smoother in that orientation. I am not doing what I'd think is process intensive: a map view, some buttons, some labels, and some quartz drawing, yet some basic quartz animation seriously slows down really badly.
Does anyone know if landscape mode is just terribly handicapped compared to portrait, and/or if so, if there are better ways to create a landscape app? I simply use a root rotated view transformed 90 degrees and attach all my sub views to it.
Thanks.

There should be no real difference between landscape and portrait orientations when it comes to rendering performance. Are you using a transform to rotate your main view 90 degrees? As of iPhone OS 2.1, I believe, you no longer need to manually apply a transform to your main view to get it to start in landscape. All I had to do to force landscape orientation was to place this delegate method within my application delegate:
- (void)application:(UIApplication *)application willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientation duration:(NSTimeInterval)duration;
{
// This prevents the view from autorotating to portrait in the simulator
if ((newStatusBarOrientation == UIInterfaceOrientationPortrait) || (newStatusBarOrientation == UIInterfaceOrientationPortraitUpsideDown))
[application setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
}
and the following in my root view controller:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return ( (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight));
}

Maybe you do some divisions which result in non-integer pixel positions ( like 0.76 ). I had some issues with performance when i had non-integer pixel positions. (Though i am not completely sure these were connected. But maybe it helps you)

Thank you for all your suggestions and help, everyone. I tried Brad's suggestion of setting the view controller autorotate settings and it worked extremely well. I think that was a huge contributing factor to the slowdown.

Related

iOS how to stop view rotate

I want my iPad app to stop rotation as you rotate the iPad. I want to stop rotate every view.
Any ideas help?
if you want stop rotation for whole app then simply in app info.plist file changed Supported interface orientations ,Initial interface orientation property to portrait or landscape depends on you
In iOS6 shouldAutorotateToInterfaceOrientation has be deprecated. Override both supportedInterfaceOrientations and preferredInterfaceOrientationForPresentation instead.
Please see
Just check the auto-resizing property of your view controller.
(Fixed syntax error)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if(interfaceOrientation == UIInterfaceOrientationPortrait)
return YES;
return NO;
}
In My Project's info.plist I have deleted some key on the iPad Supported interface orientations like the following image (I have only given support for the portrait orientation)
The main idea of global controllable rotation lock is to write UIViewController category containing lock mechanism for every view controller.
You simply need to modify supportedInterfaceOrientations method globally
- (NSUInteger)supportedInterfaceOrientations
{
return __orientation;
}
Here __orientation is the static variable which can be set via category method.
The full realization of the category is presented here
Please update your projectname.plist like this. Supported interface orientations have only one object "Portrait (bottom home button)"
I strongly advise against stop rotation on iPad because supporting rotation is a must on the iPad. This is because the iPad does not have a normal way in which it will be held unlike the iPhone, which is normally held in portrait view (AKA Vertical). So you have to leave the choice to the user to eventually lock the orientation
The HIG do not actually state this as a requirement, but as a recommendation but there are many app that was rejected by this issue.
By the way if you want to this for a limit number of view controller you should implement:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if(interfaceOrientation == UIInterfaceOrientationPortrait){
return YES;
}
}

How to get InterfaceOrientation from iPhone (not DeviceOrientation)?

I've created a modalviewcontroller and all the subviews are created by code. When I'm testing the app, I find a problem. Then main cause of the problem is that an app shouldn't support UpsideDown orientation, but devices may happen to be in that orientation.
If I:
Rotate the device to Portrait orientation, and then to UpsideDown mode and presentModalView, the subviews in modalviewcontroller should appear the same as Portrait orientation.
Rotate the device to Landscape orientation, and then to UpsideDown mode and presentModalView, the subviews should be treated differently.
The above situation tells me that I should create subviews in modalviewcontroller according to previous InterfaceOrientation.
The problem is: How to get the previous screen's InterfaceOrientation? Getting the device orientation won't do any help in this situation.
PS: I'm writing a lib, I may give my users the interface to send me the "toInterfaceOrientation" from -willRotateToInterfaceOrientation:duration: but are there any ideas about how to get the orientation in my code?
In any UIViewController you can access the property interfaceOrientation like this:
if (self.interfaceOrientation == UIInterfaceOrientationPortrait) {
// do stuff
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}

Determine UIInterfaceOrientation on iPad

I don't need to specify the orientation in this case, I just need to detect it, but I'm having trouble. I have conditional code that should only work in portrait, and if the device is in landscape I need to do something else. Since the deviceOrientation is not necessarily the same as the interfaceOrientation, I can't come up with a way to test for portrait mode.
Most tutorials I find on Google are ways to force landscape or do some sort of rotation. The only thing I want to do is just determine what the orientation is. Here is my code, which is not working:
-(void)viewDidLoad {
[super viewDidLoad];
//currentOrientation is declared as UIInterfaceOrientation currentOrientation
currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
NSLog(#"%#",currentOrientation); // == NULL
}
I need to determine the value of the interfaceOrientation and program conditionally. Thanks for your help!
Are you aware of the interfaceOrientation property of the UIViewController class?
- (void) viewDidLoad {
[super viewDidLoad];
BOOL isPortrait = UIDeviceOrientationIsPortrait(self.interfaceOrientation);
// now do whatever you need
}
Or are you after [[UIDevice currentDevice] orientation]?
Especially at launch I have found the following to be always accurate for the UI, regardless of what the UIDevice says the orientation is.
[UIApplication sharedApplication].statusBarOrientation
self.interfaceOrientation is unreliable in certain situations. For example, re-arranging tabs in a tabbar application returns incorrect value.
However [UIApplication sharedApplication].statusBarOrientation is always reliable. You saved me a lot of time slycrel. Thank you.
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if ((orientation == UIInterfaceOrientationLandscapeLeft)
|| (orientation == UIInterfaceOrientationLandscapeRight) )
{
//Landscape
}
else
{
//Portrait
}
I know it is a very old post. How ever I would like to add a point to say it is better to check status bar orientation is better. When ever you call self.interfaceorientation it is calling shouldRotateToOrientation every time. If you have written some code in that method it will be executed. So be cautious!.
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
if(deviceOrientation == UIDeviceOrientationFaceUp || deviceOrientation == UIDeviceOrientationFaceDown){
if(debug){
NSLog(#"Nothing to change because it is gone to Flat");
}
return;
}
if(deviceOrientation !=statusBarOrientation){
if(debug){
NSLog(#"\nApple has a bug?:\n UIDeviceOrientation : %d, UIInterfaceOrientation: %d",deviceOrientation, statusBarOrientation );
}
}
You won't believe me until you will see at the console the second output!
Some situations - and they exists! - is displayed the last NSLog content!
Than you have to do some workarounds to go on that way, where iOS has no bug, good luck for everyone!
Ah that ... forum moderator maybe will delete this post too, because this doesn't meant to be and answer in his opinion!
I hope it helps for somebody once, it happens on iphone too...(there I got)
Mix it up a little:
BOOL isLandscape = self.view.frame.size.width > self.view.frame.size.height;
(edit) Obviously the previous answers are the correct way to do this and this solution would fail in a situation where view controllers are not full-screen.
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{</br>
if (UIDeviceOrientationIsLandscape(toInterfaceOrientation)) {</br>
some instructions;
} else {
some instructions;
}
}
This is a snippet from one of my programs.
You could of course use the if statement in your ViewDidLoad notification as well.
I already voted up the answer by #slycrel, but I would like to take the time to write this, and point some things out that seems to be lost in this old question, and lots of other questions on the subject.
It's true that Apple does not really want us to update most of our UI based on orientation changes, but it is still totally possible and sometimes necessary on a case by case scenario, and it will be that way until Apple improves their new(ish) APIs (e.g. viewWillTransitionToFrame: would be way more useful than viewWillTransitionToSize:. Just sayin')
Why I voted up the answer by #slycrel is related to what you need to keep in mind as the logical difference between UIDeviceOrientation and UIInterfaceOrientation.
Tthe status bar is what denotes an application's currently known UIInterfaceOrientation. All this stuff about FaceUp, FaceDown is only related to a device's orientation, not necessarily your application's. An application does not support device orientations anyway. Really, UIDeviceOrientation can be ignored completely if all you have to do is make sure you layout and animate things appropriately in your interface, which is 99% of an application developer's use cases. This is currently achieved with the status bar's UIInterfaceOrientation from #slycrel's answer:
[UIApplication sharedApplication].statusBarOrientation
It should be noted, the readwrite version of this property is deprecated, the readonly version is not.
Take this example:
I have an application that supports ALL interfaces orientations, and a root view controller that supports them as well.
Now, I am presenting a UIViewController that will result in the status bar orientation to become landscape.
Which landscape orientation (left or right) it goes to is based on what is returned by preferredInterfaceOrientationForPresentation for that view controller, what the current device orientation is, and what interface orientations the view controller supports (see next point).
The status bar will go to landscape, regardless of what the current device orientation is, because this view controller only supports landscape based on what is returned by supportedInterfaceOrientations. Lets say we support both landscape left and right with UIInterfaceOrientationMaskLandscape.
I also want to conditionally animate this view controller into position with a rotation transform. This will only be necessary when going from portrait or portrait upside down, to landscape left or landscape right. Otherwise it will be a more simple presentation animation without rotation.
Then, after some time and device use, I dismiss that view controller.
Now I want to conditionally animate this view controller off the screen with another rotation transform. This will only be necessary when going from landscape left or landscape right, to portrait or portrait upside down. Otherwise it will be a more simple dismissal animation without rotation.
At this point, the status bar's orientation will become whatever the system decides is appropriate for the combination of your root view controller's preferred interface orientation and supported interface orientations, as well as the device's current UIDeviceOrientation.
Since the view controller we are going to supports ALL interface orientations, if your device's orientation is FaceUp or FaceDown, you can not reliably guess the next UIInterfaceOrientation based on UIDeviceOrientation, and you do not have to anyway.
So... status bar orientation to the rescue!
The previous example is possible, because the status bar orientation is not updated when a view controller transition is about to start (the system asks a transition delegate for an animator, etc.). Then it is updated when the transition starts animating (e.g. by the time animationTransition: is called). This way you should have a good comparison just using the initial and current values of the status bar's UIInterfaceOrientation.
Even without using view controller transitions, it should still be safe to update views based on the status bar orientation.
Keep in mind, if you are manually updating the status bar, and if you are not using "View controller-based status bar appearance" in your Info.plist, then your application's logic must be aware when the status bar will and did change orientation. You will probably be looking for a couple NSNotification names for these cases, which are:
UIApplicationWillChangeStatusBarOrientationNotification
UIApplicationDidChangeStatusBarOrientationNotification
As well as these UIApplicationDelegate methods:
- (void)application:(UIApplication *)application willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientation duration:(NSTimeInterval)duration;
- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation;
- (UIInterfaceOrientationMask)supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window
And this other helpful UIApplication property:
#property(nonatomic,readonly) NSTimeInterval statusBarOrientationAnimationDuration;
As of iOS8, APIs have been deprecated or return unhelpful results such as .FaceUp .FaceDown
This is because Apple does NOT want you to update your UI using orientation, but rather by using size classes, constraints, and proportion (using n% of superview).
Indeed, orientation dependent code might fail to provide good results across the whole range of device and use case (especially multitasking)

iPhone OS: Rotate just the button images, not the views

I am developing an iPad application which is basically a big drawing canvas with a couple of button at the side. (Doesn't sound very original, does it? :P)
No matter how the user holds the device, the canvas should remain in place and should not be rotated. The simplest way to achieve this would be to support just one orientation.
However, I would like the images on the buttons to rotate (like in the iPhone camera app) when the device is rotated. UIPopoverControllers should also use the users current orientation (and not appear sideways).
What is the best way to achieve this?
(I figured I could rotate the canvas back into place with an affineTransform, but I don't think it is ideal.)
Thanks in advance!
Just spouting off an idea (not sure if it would work or not)...
Perhaps you could have your screen controlled by a UIViewController that supports all orientations, but have the canvas be controlled by one that only supports a single orientation (ie, returns NO in its shouldAutorotate... method).
If that doesn't work, I'd probably just go with the affineTransform route.
I discovered a way to do this, similar to what Dave DeLong proposed.
Using a transform worked, but it wasn't ideal. Although the end result (end of the animation) was what I wanted, it would stay show some kind of shaky rotation animation.
Then I found this:
https://developer.apple.com/iphone/library/qa/qa2010/qa1688.html
Which says that a second (or third etc.) UIViewController added to the WINDOW would not receive rotation events, and therefore would never rotate. And that worked!
I created a 'fake' UIViewController with a blank view and added that as the first view controller. This receives the rotation events which I then pass on to the other view controllers that can then choose whether to rotate - the entire view or just button labels.
It is a bit hacky... But I guess the user won't notice.
Using the willRotateToInterfaceOrientation method, you should be able to use some simple logic to swap out the images:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
//The following if statement determines if it is an iPad, if it is then the interface orientation is allowed. This line can be taken out to support both iPhones an iPads.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
//Swap images and use animations to make the swap look "smooth"
//NSLog(#"Landscape Right");
} else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
//Swap images and use animations to make the swap look "smooth"
//NSLog(#"Landscape Left");
} else {
//Swap images and use animations to make the swap look "smooth"
//NSLog(#"Portrait");
}
} else {
}
}
To change an image in your interface programmatically:
[myUIImageView setImage:[UIImage imageNamed:#"myImage.png"]];
Also, to make sure the view doesn't auto-rotate use the shouldAutorotateToInterfaceOrientation method to tell your app to stay in portrait.

How do you handle Portrait and Landscape Views?

I understand you can specify a landscape, for the entire application but what if it's partially in landscape and partially in portrait.
Currently I have some views that are basically Images. These images have been rotated so that the user knows certain sections of the application are going to be in Landscape mode. All my UILabels are also rotated to give this effect as well.
My question is, is there a better way to handle this. Is there a way to set the orientation programmatically at run time? In which case I would no longer need to rotate my images/uilabels.
Just to clarify, I do not need auto rotation functionality, the way that it is being implemented now is captures all the functionality I want to include in the app but I just wanted to know if there is a less cumbersome way of handling landscape/portrait views within the same application.
You can force rotation at any time by calling;
UIApplication *application = [UIApplication sharedApplication];
[application setStatusBarOrientation: UIInterfaceOrientationWHATEVER animated:NO];
My current application is primarily landscape, but has a few portrait views. In the view controllers corresponding to views the user should be able to rotate, I am allowing the rotation but preventing animation. This gives you a switch to another view in your NIB, without any weird slide-off-the-screen screwyness that normally happens is you pile on a view during the animation.
Hopefully you find this helpful!
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if (interfaceOrientation == UIInterfaceOrientationPortrait) {
rotatingToPortrait = YES;
[UIView setAnimationsEnabled:NO];
return YES;
} else if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
rotatingToPortrait = NO;
[UIView setAnimationsEnabled:NO];
return YES;
}
// Catch upside-down
return NO; }
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[UIView setAnimationsEnabled:YES];
if (rotatingToPortrait) {
// Swap in portrait view here
} else {
// Swap it out here
} }
Currently I do not know of any way to control orientation programatically. Meaning there is no way to tell the device "rotate to landscape now". You can only specify things like:
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
You can specify what view controllers support what orientations, and react to the orientation changes by overriding functions, however when and how those functions are called is determined by the system. You can get more detailed messages from the UIDevice class too.
If I understand correctly what you are saying, your app is essentially always in one single orientation, however you are just drawing your various views differently to make it seem like certain parts of the app are in portrait/landscape mode? It sounds like you are trying to fit a square in a round hole, the iPhone's orientation API's weren't designed for that kind of behavior, and you are better off working with the API's than against them.