I add a "align" constraint, but Xcode add a "pin" constraint autolayout - xcode6

When we add constraints, we have the choice between "Align" button in the auto layout toolbar or "Pin" button.
In my storyboard, if I add a new alignment constraint "Bottom edges" between a scrollview and his container.
The icon of this constraint is 2 squares and a line.
But after, in the list of constraints of my scrollview, the icon is different :
The icon is a "Pin" icon.
I don't understand why.
One more question, I think it's related : what is the difference between "Align bottom" and "Bottom space" ?

Pin and Align are just abstractions to make it easier to understand what you are setting up. In reality, a constraint is a relation between attributes of two objects. What you specify in Interface Builder with align or pin gets translated into an NSLayoutConstraint object.
When done programmatically, there is no pin or align option, you are just specifying the objects, their attributes (.Top, .Bottom, .CenterX, etc.) , the relation (.Equal, .GreaterThanOrEqual, .LessThanOrEqual), a constant, and a multiplier.
For example, here is how to align the bottoms of two buttons:
NSLayoutConstraint(item: button1, attribute: .Bottom, relatedBy: .Equal, toItem: button2, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
If the two objects are siblings, then their bottoms are considered to be aligned. If one object is a subview of the other object, then it is considered to be Bottom Space. Both are just a relation between the .Bottom of one view to the .Bottom of the other view.
When you click on the constraint and view it in the Attributes Inspector, you see the values that are used to create the NSLayoutConstraint.

Related

Resizing superview that's an embedded UIViewController to fit subviews

Here's the scenario:
I have a segmented control that toggles between hiding/displaying two views that each embed a view controller (via use of the interface builder's provided "Container View"). For simplicity's sake, in each embedded view controller I have a single subview with fixed leading and trailing spacing to its superview's margins along with fixed top and bottom vertical spacing between the subview and its superview's top and bottom layout guides. If the superview (i.e. the embedded View Controller) is a fixed width and height, these constraints should fulfill the x-position, width, y-position, and height requirements (respectively).
Here's the problem:
I want to add a height constraint to the subview. If instead of embedding a view controller in the container view I had just placed the subview (with the added height constraint) inside a container view (that didn't have a fixed height constraint), the container view would be automatically resized to fit its subview. However, because the container view embeds a view controller, auto-layout doesn't consider the constraints set between View Controllers.
In other words, I want the "Container View" (or the embedded View Controller) to be resized in height according to the subview's height constraint.
Here's the type of solution that I'm looking for:
Ideally, I would like the solution to this problem to be as clean as possible, which in my eyes means:
1) Sticking with the interface builder and storyboarding.
2) IBOutlets for NSLayoutConstraints.
3) Subclassing if need be.
However, any working solution besides the one that I proposed (which was to not embed a View Controller) would help me out.

How to implement scroll view in xib cocoa objective-c

In order to implement scroll view I do:
Create Cocoa Application
Go to XIB
Drag scroll view to the view window and set its constraints to 0
Everything seems fine until now
Under Bordered Scroll View (in the Document Outline) I press on Clip View and then View and resize that to any large number (under size inspector)
I add a button (for the sake of it) to the view (under clip view) (in the Document Outline) and sets its constraints
After this I immediately get the "Ambigious Layout. Position is ambigious for "View".
What am I doing wrong? Is this the proper way to add scrollview? It also seems rather difficult to add items to the scrollable area as I dont see the entire scrollable area in the xib.
Please help a noob.
In general this is a correct way to add a scroll view. (You can also create a view or set of sibling views, select them, and choose Editor > Embed In > Scroll View.)
If a view has no constraints, then Xcode will add sufficient constraints at build time. These constraints are not necessarily the ones that cause the view to behave like you want as things change size, but they're good enough to maintain the current layout of the canvas when things have their current sizes.
However, once you add constraints, Xcode will start insisting that the constraints are mutually-compatible (no conflicts) and sufficient to be unambiguous.
So, that explains why you get that warning. You have added some constraints, but not enough to make the layout unambiguous. You need to add enough. Xcode should explain in more detail what's needed, although there will necessarily be multiple possibilities for how to resolve the ambiguity.
In your case, I'm guessing that the size of the view in the scroll view is ambiguous. For example, you may have added constraints to position the button relative to the top and leading edge, and the button likely has intrinsic size, but you haven't constrained the view's bottom or trailing edges to the button. So, the size of the view could be anything.
Of course, rather than constraining the view's bottom and trailing edge to the button, you could just add explicit height and width constraints to it. Or whatever.
You may also need to constrain the view to the clip view.
You can also use Editor > Resolve Auto Layout Issues > Add Missing Constraints and see what Xcode adds. You can then change things from there if what Xcode added is not what you want.
For my Mac OS X app, I selected the controls on xib to embed in scroll view ( Editor > Embed In > Scroll View ) and applying the following constraints to Custom View (inside Scroll View -> Clip View) did work.
Where hight is to accommodate controls.

Is there a way to shrink a constraint with autolayout without code?

Without using code, I'm basically trying to achieve the "Desired outcome" in this picture:
I want the constraint on the "Hello!" label to shrink its length when the screen height is shorter.
As you can see in "Actual result", the Button in the bottom is off the screen. I want the image view to have fixed width and height.
I know I can create IBOutlets for constraints and doing it by code like this kind of posts suggest (autolayout - make height of view relative to half superview height), but I'm trying to avoid using code as much as possible.
Side question: If there's no way to do this in IB, what are the best ways to do this in code?
Thanks for the help!
Yes. The easiest way to have this kind of "split height" constraint is to put a "header" view between your image view and the top of the screen, and embed your "Hello" label inside this new header view. Then add a constraint to keep the "Hello" label vertically centered inside the header view.
To keep the header view the right size, add constraints to keep the top of the header view pinned to the top of the screen, and the bottom of the header view to the top of the image view.
Then you'll just add constraints to keep the button and image view pinned to the bottom of the screen. (Or, see comment from Sulthan, below.)
In Xcode 5.1 (in beta), there is UI to make more general constraints, including the ones you want, but you have to do it like this or in code in earlier versions.

Resizing scroll view with auto layout?

It's a common technique to wrap content in a UIScrollView for the purpose of moving it out of the way when a keyboard appears. This is done by modifying the frame/bounds of the scroll view, so that it encompasses the area not covered by the keyboard. According to Ole Begemann, one shouldn't use the frame property when using autolayout.
How does one accomplish this same effect without using frame?
You can create an outlet to your constraint(s) in IB, e.g. to the constraint that connects the bottom of the UISCrollView to the superview, and then use code to change the constant of that constraint. This can also be animated in an animation block.
self.someConstraint.constant = ...;

Objective C: Adaptive Toolbar On Orientation Change

I am having a problem with my toolbar when i change the orientation of my iPad.
i set my nib file into landscape and everything is all right but when i turned it to portrait my toolbar still has the width from the landscape orientation.
how will i make my toolbar adaptive to the orientation change to portrait?
Landscape:
Portrait:
thanks!
Try adding UIViewAutoresizingFlexibleWidth to the toolbar autoresizingMask like so:
myToolbar.autoresizingMask |= UIViewAutoresizingFlexibleWidth
Or, if your doing this in the Interface Builder, make sure this horizontal bar is selected (others may be selected as well, which is fine):
More from the UIView Class Reference about autoresizingMask:
When a view’s bounds change, that view automatically resizes its
subviews according to each subview’s autoresizing mask. You specify
the value of this mask by combining the constants described in
UIViewAutoresizing using the C bitwise OR operator. Combining these
constants lets you specify which dimensions of the view should grow or
shrink relative to the superview. The default value of this property
is UIViewAutoresizingNone, which indicates that the view should not be
resized at all.
When more than one option along the same axis is set, the default
behavior is to distribute the size difference proportionally among the
flexible portions. The larger the flexible portion, relative to the
other flexible portions, the more it is likely to grow. For example,
suppose this property includes the UIViewAutoresizingFlexibleWidth and
UIViewAutoresizingFlexibleRightMargin constants but does not include
the UIViewAutoresizingFlexibleLeftMargin constant, thus indicating
that the width of the view’s left margin is fixed but that the view’s
width and right margin may change. Thus, the view appears anchored to
the left side of its superview while both the view width and the gap
to the right of the view increase.
If the autoresizing behaviors do not offer the precise layout that you
need for your views, you can use a custom container view and override
its layoutSubviews method to position your subviews more precisely.
In addition to adjusting the flexible width of your toolbar you could create 2 arrays of toolbar items. One for portrait and one for landscape. Fortunately you only have to create the toolbar items once and just add them to the appropriate array(s).
Then during the orientation change you can set the toolbar's items array to the appropriate one.
Good Luck