Working example
Hi. At first, here is working code scroll view example writed couple of days ago.
[self addSubview:scrollView];
id views = NSDictionaryOfVariableBindings(scrollView);
[self addConstraints:PVVFL(@"H:|[scrollView]|").withViews(views).asArray];
[self addConstraints:PVVFL(@"V:|[scrollView]|").withViews(views).asArray];
Constraints writed in code and with help of Parus lib.
As you can mention, scroll view is tied to it's superview. In another words, it fill it completely.
Couple of lines earlier i setup an scrollView
tree.
id views = NSDictionaryOfVariableBindings(photoView, storeNameLabel, selectStoreButton, tagsLabel, tagsContainer, editTagsButton, commentView, sendButton, cancelButton);
[scrollView addConstraints:PVVFL(@"V:|-15-[photoView(150)]").withViews(views).asArray];
[scrollView addConstraints:PVVFL(@"|-15-[photoView]-15-|").withViews(views).asArray];
[scrollView addConstraint:PVCenterXOf(photoView).equalTo.centerXOf(scrollView).asConstraint];
[scrollView addConstraint:PVTopOf(storeNameLabel).equalTo.bottomOf(photoView).plus(20).asConstraint];
[scrollView addConstraints:
PVVFL(@"|-15-[storeNameLabel]-(>=15)-[selectStoreButton]-15-|")
.alignAllBaseline.withViews(views).asArray];
[selectStoreButton setContentCompressionResistancePriority:UILayoutPriorityRequired
forAxis:UILayoutConstraintAxisHorizontal];
[scrollView addConstraints:
PVVFL(@"V:[storeNameLabel]-15-[tagsLabel][tagsContainer]").alignAllLeft.withViews(views).asArray];
[scrollView addConstraint:PVRightOf(tagsContainer).equalTo.rightOf(selectStoreButton).asConstraint];
[scrollView addConstraint:PVTopOf(editTagsButton).equalTo.bottomOf(tagsContainer).plus(10).asConstraint];
[scrollView addConstraint:PVWidthOf(editTagsButton).equalTo.widthOf(tagsContainer).asConstraint];
[scrollView addConstraint:PVLeftOf(editTagsButton).equalTo.leftOf(tagsContainer).asConstraint];
[scrollView addConstraint:PVTopOf(commentView).equalTo.bottomOf(editTagsButton).plus(10).asConstraint];
[scrollView addConstraint:PVWidthOf(commentView).equalTo.widthOf(editTagsButton).asConstraint];
[scrollView addConstraint:PVLeftOf(commentView).equalTo.leftOf(editTagsButton).asConstraint];
[scrollView addConstraint:PVHeightOf(commentView).moreThan.constant(100).asConstraint];
[scrollView addConstraint:PVLeftOf(cancelButton).equalTo.leftOf(commentView).asConstraint];
[scrollView addConstraints:PVVFL(@"[cancelButton]-(>=15)-[sendButton(==cancelButton)]").alignAllBaseline.withViews(views).asArray];
[scrollView addConstraint:PVRightOf(sendButton).equalTo.rightOf(commentView).asConstraint];
[scrollView addConstraints:PVVFL(@"V:[commentView]-10-[cancelButton]-10-|").withViews(views).asArray];
How you can see, this is pretty complicated layout.
But key points of it: Internal views have fixed heights, provided by theirs intrinsic content sizes. Combined all together they tried to increase height of scrollView
.
But scrollView
height is fixed by self.view
!!! Constraint solver must generate error. But,
Theory
Apple has special Tech note for this case. And there is some interesting moment:
To make this work with Auto Layout, the top, left, bottom, and right edges within a scroll view now mean the edges of its content view.
Also this note provide some examples of different approaches when working with scroll views and auto-layouts.
Now i will try to answer your questions.
Answers
Question 1 - Why is this?
As you can read above, this is because auto-layout for scroll view setup content view sizes and not frame sizes.
Question 2 - why is this?
Again, thing is in content size. Special constraint approach looks like hack over interface builder. At xib you have normal size view, and after nib-file instantiating you just back things to normal, fixing this constraint to 0, which mean that content size of scroll view will be equal to C view.
Question 3 - Can someone please explain what's happening when a scrollview scrolls, which object's frame origin is actually changing, and why is it done this way?
Great explanation of this process you can find at this article: Understanding Scroll Views, but short answer is: UIScroll view perform scrolling by changing self.bounds.origin
point.
Question 4 - Can anyone explain how the constraints should be set between (A), (B), and (C) in plain English?
You should set constraints inside the scroll view by fixing all edges to internal view. In another words, all edges of scroll view must be fixed twice: By internal views and by superview.
If answer on this question are not clear yet, you can read this answer from very beginning.