portrait layout wont scroll in landscape orientation - ios

Im quite new to XCode and Interface Builder, so forgive me if the solution is obvious.
I have designed a nice portrait IPhone view in interface builder (XCode 5) and have set the constraints on each of the elements (labels, text views, switches, buttons etc) so that they are positioned correctly in either 3.5 or 4 inch portait mode in the simulator.
However, when I rotate the simulator to landscape it breaks the design with elements overlaying each other and other elements disappearing (being clipped from the view) - and I expected this.
My idea of a solution is to put all of the UI elements inside a UIScrollView and set constraints on the scroll view so that it fills the screen in either portait of landscape mode.
After doing this, the portrait view is as before in the simulator, but in landscape view nothing scrolls, and none of my UI elements respect their constraints (stretch horizontally etc). Im still losing UI at the bottom and I cant scroll it into view.
I assumed that putting everything into the scroll view would simply 'fix' this issue, but the scroll view seems to do absolutely nothing at all. I have fiddled with various settings in interface builder but nothing fixes this.
There seem to be lots of long-winded solutions to this type of scenario based on code, but surely something this simple and common should just 'work'
What am I missing, or what have I done wrong, or does simple scrolling really have to be extensively coded in order to work ???

Putting all of your elements inside a scroll view won't really solve anything. Those elements would still need constraints to know how to position themselves in the scroll view. You need to be careful as well, as this solution sounds like something that goes against apples human interface guidelines. I'd advise against ignoring those, as Apple are known to reject apps that do this.
I'd say your problem is your constraints simply aren't setup correctly if elements are cover other elements and moving into the wrong places when rotated.
Annoyingly the WWDC videos section of the developer site is still down, but when it's back up, have a watch of the video of autolayout in Xcode 5, it will help explain what's going on.
If you want elements to completely change position when rotated however, you're likely to need more than just constraints, and would need to throw in some code to handle the transition between portrait and landscape. So it really depends on what the view is supposed to do when you rotate the device

OK, Ive figured it out. It IS a bug in either XCode 5 or IOS 7
I created 2 simple iphone UI's in interface builder - one in Xcode 4.6.3 targeting IOS 6.1 and the other in XCode 5 Beta 4 targeting IOS 7 beta 4.
The first app ran entirely as I had assumed, with the scroll view scrolling in landscape mode. The second app had no scrolling at all in the scroll view - so obviously a bug.

Related

Why is iOS simulator displaying blank screen when I rotate device?

Getting through some introductory swift and playing with Xcode and I basically just have a page with some color squares, background color etc. Doesn't do anything. Problem is when I compile the code it will run in simulator just fine and show everything perfect, BUT when I rotate the device, everything disappears and it only gives me a blank white screen. Rotating right or left does it. The only view that shows it is the original upright view (for all iPhone devices that I tested on through the simulator).
Xcode 6.1.1 and iOS Simulator 8.1 are being used on my MacBook Air with OSX 10.9.5.
In the App general page, I have already checked under Deployment info that Landscape Right and Left are both checked on. Storyboard is set on Any H and Any W.
I'm not sure what I'm doing wrong and it has been pretty difficult searching since I'm still new to iOS development I'm not sure I'm using the right words or whatever because I can't find an answer.
Summary:
App displays properly in iOS Simulator, Portrait View but no other views work and will display blank white screen instead.
In order to see if your views are actually being drawn and just off screen as others have suggested capture the view hierarchy. Go to 'debug' in the menu, then in 'view debugging' click capture view hierarchy. This will pause your app and create a 3D representation of all view on your screen which you can move around by clicking and dragging.
Are your views actually being drawn? If yes are they drawing off screen? If yes then you need to fix your constraints.
It sounds like you haven't set your constraints appropriately. Try setting the top and leading constraints for each of your views to something less than 320 (should cover all device sizes). Fix your warnings, then try again. I believe the views are simply off the screen.
You don't have the correct auto-layout UIConstraints set in interface builder. Check the document outline view in interface builder and ensure that you have appropriate constraints set on each view.
Auto Layout issues occur when you create conflicting constraints, when you don’t provide enough constraints, or when the final layout contains a set of constraints that are ambiguous.
Check this Apple documentation out, it will show you step by step how to resolve your (common) issue.

Screen Shift on UIInterfaceOrientationLandscapeRight

I've got this application mainly displaying photographs.
The app was originally written for iOS 3.1 and upgraded to 4 before beeing published. It was not touched ever since. Now that the owner of the API appied some changes which ain't as compatible as they thought, I am forced to update the app. So I'll have to go for iPhone 5 and 6 and 6+ and iOS 7 and 8 updates in one go.
I observe this behaviour in the simulator of iphone 4, 5 and 6+ dimensions.
Portrait looks fine.
Landscape left looks fine too.
Landscape right is screwed up. Apparently it looks as if the whole screen were shifted to the left.
This is strange because I am not aware of anything that I would do different for landscape right or left. All I am doing is differnicating between any portrait and any landscape orientation.
It worked fine in the old version. But frankly I cannot reproduce this any more because I don't have access to the old xcode and sdk versions. But the app is in store for years and works fine on modern devices and modern OS versions.
A bit more background info, just in case it is of importance:
The app is based on a UITabBar, but it is not visible in this view.
The image is scrollable. It is placed on one view three times of the size of the screen with preceeding and succeeding image views place to the left and right respectively. This view with the three images is placed within a scroll view of the size of the screen or window respectively. This concept still works file, it is just shifted.
When I check the view item's frames in debugger or with NSLog, they all seem to be right, starting at (0.0/0.0) or respectively.
The view on the bottom with the four buttons that navigate to related functions and their view controllers, is re-alligned programmatically on each rotation, as well as the overlays with the textual information. All works as it should but it's shifted in this one orientation.
Well, all views are layouted programmatically on each rotation.
There are no constraints defined.
iOS6/7 deltas are all set to 0.
The app "wants fullscreen". By tapping on the image all UI items disappear and re-appear on the next tab. (Just by setting the .hidden attribute. Except for the navigation bar. Thats managed using setNavigationBarHidden:animated: with YES on animated) Works fine, even in the shifted view.
I am running out of ideas.
While I put all the details together for the question, eventually one idea came to my rescue.
The issue is related to hiding the tab bar. I could not use the regular way of hiding the tab bar because then it would not re-appear when navigating down to the functions that are associated with the buttons on the bottom overlay view.
Therefore I did some sort of hack. I did not hide it regularily but moved the tab bar out of the screen.
AND: This was the only thing that I did differently for landscape right and landscape left. I just searched for the constant names and found it.
Apparently, manipulating the tab bar view had a flaw in older iOS versions. (Or in older SDK versions, I am still working on that important detail)
To overcome the flaw the tab bar view was modified this way for landscape right:
[self.tabBarController.view setFrame:CGRectMake(0-kTabBarHeight,0,width+kTabBarHeight,height)];
This does not seem to make sense but did help me out a lot on similar issues years ago when the app was written.
Now, I changed this to:
[self.tabBarController.view setFrame:CGRectMake(0,0,width+kTabBarHeight,height)];
which is the same for landscape left too.
For the time beeing I separate between iOS versions >= 8.0 and smaller. But I'll double check that with older devices and may get back to this answer later.
I leave the question posted because I found the original "hack" here on SO too, so that I guess that others will have the same issues when updating to ios 8 or SDK 8 respectively.
Thanks for listening.

UIViewController Size doesn´t work

Hi im currently developing an Universal app for iPhone, iPod and iPad. I have all view controllers in both storyboards set to Inferred. It works fine on iPhone Retina and on all iPads but when you put it in landscape mode it gets all messed upp and on the iphone 3,5 inch simulator the bottom gets cut off. How can i fix this? Do i have do create seperate view controllers for landscape mode and iphone 3,5? And the write some code that recognizes if its in landscape mode and iphone 4? I thought this worked automatically. Or have i done something wrong?
There is no quick fix/answer to your question.
Since the screen size is different while using horizontal and vertical orientations - it is simply not the same canvas and thus you will need to do some manual work to set it right.
Strategy 1.
Assuming your layout is simple - there are not too many elements and all elements can theoretically fit both horizontal and vertical screen size:
You should use auto layout from the Interface builder - Look at an excellent video from WWDC
https://developer.apple.com/wwdc/videos/
(video 406 - Taking Control of Auto Layout in Xcode 5)
In few words - you set spacers to your elements, aligning them to the end of your view (dynamically), therefore you can make your element shrink and move automatically respecting the current screen orientation.
Strategy 2.
Assuming your UI is complex and will not fit both orientations:
have a different xib file for horizontal and vertical views, this can take some time, but it is a solid solution that always looks good.
You simply need to track changes in orientation and load the appropriate xib.
Your problem will only be solved if you use Autolayouting and for that you need to go through some tutorials
Ray's Tutorial
Another Very well explained tutorial
Going through the above articles will definately help you in solving your problem

iOS storyboard layout

I am working on an app and have come into some graphical problems when designing my app.
First off, my app is only support by iPhone. My current storyboard is using the iPhone 5 as the screen size, so everything screws up when I try to run in iPhone 4 and 4S. Is there a way to make multiple storyboards for each different screen size? Or do you all have another solution?
Thanks!
- Brad
There is a way to make different storyboards for separate screen sizes, but another way to do it is like this:
Whenever you add objects to your views, be sure to have them aligned to something (using constraints). If all items are relative to other items, then most likely the layout will be fine on all devices. Also, if you find that your controls start overlapping, then perhaps you ran out of room. In that case simply add a scroll view to your layout, and then put the controls on top of it. Then, it won't scroll on the larger screens because all controls are shown, but on smaller devices it will allow you to scroll down to see the rest of the objects.
Good luck.
There is a small button in the lower right hand corner that lets you toggle between 3.5" and 4" screen sizes so you can see how it will look on different devices. By using Auto Layout introduced in iOS 6 you can make sure to set up your constraints so that your UI looks good on both older and newer iPhones.

iOS autolayout performance issue in portrait mode. [NSISEngine optimize]

I have encountered a very strange problem and I was wondering, if anyone could help me out here since I'm totally lost.
Context:
I am developing an app with a relatively simple hierarchy. Just a few view controller but quite a lot of high-res images. They are presented in a UIScrollView with some text etc. While testing it in portrait mode the scrollview didn't scroll smoothly at all. It seemed like the framerate droped to about 4-5 fps. First I thought it was because of the high-res images.
But then I turned the iPad to landscape mode and everything ran smoothly. Since the I have a separate xib-file for portrait and landscape, I thought there has to be a problem in the portrait-xib. It turned out, there wasn't. Both had the same VC-class and where therefore using the same code and both xibs are almost identical except for the sizes and positions of the views.
To narrow the problem down, I used Instrument's TimeProfiler to see whats causing the problem. As it turned out, TimeProfiler showed some calls to [NSISEngine optimize] (triggered by NSLayoutConstraint).
In portrait mode were more calls and those calls took much longer. Further down the tree I saw that in portrait mode [NSISEngine optimize] called [NSISEngine fixupIntegralizationViolations] and in landscape it didn't.
I even removed all the viewcontroller's from the app except for the rootVC and one other which is presented by the rootVC. The presented vc just contains some images, buttons and some animations. It has only one xib for both orientations and is (as all others too) layed out with autolayout.
The layout works as it should in both orientations and there are no ambiguities (as far as i can tell. at least po [[UIWindow keyWindow] _autolayoutTrace] doesn't show any).
I've attached a screenshot of the TimeProfile of the presentation process of the vc. One for portrait and one for landscape. As you can see, in landscape the calls to [NSISEngine optimize] take only a millisecond while in portrait they take over 3000ms.
Is there anyone who can tell me why that is? Or maybe has any idea what I can do to find out what the problem is?
Any help would be greatly appreciated!
Thx
Link to a larger version of the image: link
I ran into the same issue with a moderately complex view where it performed well on non-Retina iPads or a Retina iPad in portrait mode. In landscape mode on a Retina device it took 10x longer to display a popover or push another view on the view stack. I ended up replacing the XIB file with a hand coded loadView in the view controller. That appears to have eliminated the problem. Interface builder has a tendency to create excessive constraints, so getting that under control is key to good auto layout performance.
I have also opened a support ticket on this problem.
Update:
I found the cause in my situation. It was the following set of constraints:
NSArray *constraints = [NSLayoutConstraint
constraintsWithVisualFormat : #"|[sunLabel][monLabel(==sunLabel)][tueLabel(==sunLabel)][wedLabel(==sunLabel)][thuLabel(==sunLabel)][friLabel(==sunLabel)][satLabel(==sunLabel)]|"
options : 0
metrics : nil
views : labelViewsDictionary];
It specifies that 7 labels within a parent view all share the same size and all extend the width of the parent view. I believe that the excessive relational nature of the layout was giving auto layout fits, particularly because the parent view width was not evenly divisible by 7.
To resolve it, I created an array of constraints that specify the width of each label and applied those constraints. When the device rotates the width of the parent changes so I go back and adjust the constant on the constraints to be 1/7th of the parent view width. This now performs well, the process of loading a popover now takes less than 300ms rather than 2000ms.
I filed a tech support request regarding this issue and finally got the answer, that it's most likely a bug. Bug report is filed. Hopefully they'll fix it soon. If there's any news I'll update this answer.
I had same problem yesterday in an Ipad iOS6.1 device. Instrumenting the app found that the method fixupIntegralizationViolations was taking around 300 ms every time was called (around 20 times, which is a lot) making the app absolutely useless.
My problem was very similar to the one Jack Cox comments, but I solved it differently. My constraint was:
#"H:|[allButton][inStoreButton(==allButton)][onlineButton(==allButton)][sortButton(50)]|"
The issue is that the parentView here is the full iPad landscape width, so the math of this contraint was giving each button this width: (1024-50)/3 = 324.6666667.
This is usually not a problem in autolayout since it takes care of big float numbers and round them correctly, but it seems that in iPad iOS6 Landscape rounding this numbers triggers a bug that blocks the UI. To go around it all I had to do is change the sortButton with to have 52, so each button width now is: (1024-52)/3 = 324. That's all. Now the method fixupIntegralizationViolations takes around 1ms every time is called.
The interesting thing is that using 52 gives it a not decimal width in Landscape, but it does give a decimal number in portrait : (768-52)/3 = 238.666667. However, portrait seems to not have any bug and autolayout rounds the numbers correctly.

Resources