With respect to Xcode's warnings about misplaced views, select the view controller in storyboard, tap the "Resolve Auto Layout Issues" button in the lower-right-hand corner of the canvas (it looks like a Tie Fighter from Star Wars), then select "Update All Frames in View Controller". This forces all of your views to reflect their constraints.
Using Auto Layout with UIScrollView
is a different animal; so much so that Apple felt it necessary to release a Technical Note on the issue: https://developer.apple.com/library/ios/technotes/tn2154/_index.html
When you connect all those constraints between subviews and the inside walls of a scroll view, the result is probably not what you expect. When you pin a subview to the sides of a scroll view, you are not in fact determining the subview's position relative to the scroll view. Instead, you are determining the scroll view's contentSize
. This is weird.
You are using Apple's so-called pure Auto Layout approach from the Technical Note. With this approach, the subviews' constraints must dictate the scroll view's contentSize
.
Let's take just one of your subviews and ignore all the rest, say one of the text views. And let's only think about that text view along the horizontal axis. If you wanted the text view to be constrained by the width of the scroll view without any horizontal scrolling, you would need to install a fixed-width constraint on the text view that was exactly the width of the scroll view's bounds minus the spacers. After doing this, the content size width would be the sum of the left spacer, the width of the text view, and the right spacer.
Unfortunately, you cannot install a constraint that establishes a relationship between the width of the text view and the width of the scroll view's bounds. And that's really too bad.
I don't actually recommend installing a fixed-width constraint on the text view. Instead, I would start over and use Apple's "mixed approach" from the Technical Note.
With the mixed approach, the subviews' constraints don't determine the scroll view's contentSize
. Instead, you must explicitly set the scroll view's contentSize
and the frame of a container view (i.e., a UIView
content view).
Let's go back to that UITextView
and the horizontal axis. Using the mixed approach, you could leave the constraints for the text view as they are (i.e., no fixed-width constraint). You could explicitly set the width of the scroll view's contentSize
and the width of content view's frame as early as viewDidLoad
. You could explicitly set these values to self.view.bounds.size.width
because your scroll view hugs the sides of the main view.
To implement the mixed approach, you will have to instantiate the content view (UIView
) in code and not set its translatesAutoresizingMaskIntoConstraints
property to NO
. By extension, you'll probably need to create your constraints for all those subviews in code as well (I don't know of any way around this). The visual formatting strings are tedious and repetitive, but they're actually easier to work with than constraints created in IB when configuring complex layouts (your layout is sufficiently complex).
I used the mixed approach to solve a SO challenge here: https://stackoverflow.com/a/21770179/1239263. Unfortunately, the solution hasn't been vetted yet. It's always possible that I'm nuts and I don't know what I'm talking about.