OAStackView
OAStackView copied to clipboard
Move to constraint based unit testing
Right now the unit test works by asserting the frames of the arranged views. Checking on the frame might be a brittle way to assert correctness. In order to be more sure about the correctness, it would be better to move to assert on the constraint that OAStackView generates instead.
In order to address this issue, all the code similar to:
layoutView(stackView);
[[theValue(CGRectGetMinX(view1.frame)) should] equal:theValue(0)];
Must be updated to check on stackView constraints and comparing them with the real UIStackView generated ones.
Fully agree with this.
Additionally, how do you feel about trying to match the constraints generated by UIStackView
itself ?
I've been poking around in a playground and inspecting the UIStackView
generated constraints, and they're somewhat different.
It may be interesting to set up tests that:
- configure a
UIStackView
according to the settings under test - configure a
OAStackView
with identical settings - assert that the constraints match
@bartvandendriessche comparing with UIStackView
would be great! I'm not sure however if checking the constraints is the right level, because OAStackView
might need different constraints e.g. for backward compatibility. The tests could also compare snapshots of identically set-up UIStackView
s and OAStackView
s.
I think it would be good to have a mix of both of these unit tests. I noticed that having the same frame on different iOS versions might not be possible, as applying the same constraints on iOS7 and iOS8 results in different frames after the layout pass. I think a decision regarding frame vs constraint must be taken early since it will affect the way the project will be moving forward.
Do you guys have some arguments/opinion on wether OAStackView should favour constraint over frames or the opposite?
Hmm, do you maybe have an example where the same constraints produce different results on iOS 7 and iOS 8 ?
I mean obviously iOS7 is lacking the baseline and margin oriented NSLayoutAttribute's but for the rest, it seems like constraints should lead to the same outcome.
Another question; does it make sense to mimic NSLayoutGuide
s using invisible UIView
s ?
Looking at the constraints generated by UIStackView
, it is clear that the implementation leans heavily on the use of the new NSLayoutGuide
class.
As mentioned in the "Mysteries of Auto Layout, part 2" WWDC talk (session 219), NSLayoutGuide
doesn't allow anything new per se, it just does optimises something that used to be done with invisible UIView
s.
It might be a good idea to build constraints against such invisible UIView
s where UIStackView
uses NSLayoutGuide
s.
In particular for the UIStackViewDistributionEqualCentering
and UIStackViewDistributionEqualSpacing
, I think we'll have to add invisible subviews anyway.
Some of the layout guides used by UIStackView
are:
UIViewLayoutMarginsGuide
There is at most a single UIViewLayoutMarginsGuide.
This is basically the new layoutMarginsGuide
and is used to create constraints of type "UI-canvas-connection" if layoutMarginsRelativeArrangement
is true
.
UI-alignment-spanner
There is always a single UI-alignment-spanner.
This layout guide is used to create constraints of type "UI-spanning-boundary".
The constraints are between the arrangedSubviews
edges transverse to the axis
(so Top and Bottom if axis is Horizontal, Leading and Trailing if Vertical).
These constraints are of priority UILayoutPriorityRequired
, but they are lenient in that they use >=
and <=
relations.
UI-ordering-spanner
There is always a single UI-ordering-spanner.
Like the UI-alignment-spanner, this guide is used to create constraints of type "UI-spanning-boundary".
The constraints are made against the same edges as those from the UI-alignment-spanner.
These constraints are .5 less than UILayoutPriorityRequired
, but they are strict in the sense that they use ==
relations.
UI-distributing
There can be 0 or n UI-distributing guides.
These guides are only used when distribution
is UIStackViewDistributionEqualSpacing
or UIStackViewDistributionEqualCentering
.
They basically mimic empty views in between the arrangedSubviews
.
These guides create constraints labeled "UI-distributing-edge". They constrain arrangedSubviews
edges parallel to the axis
to make sure the space in between the arrangedSubviews
is equal.
If there are multiple UI-distributing guides, they will constrain themselves to have equal width
s or height
s depending on the axis
(width for Horizontal, height for Vertical).
It'd probably be useful, for performance, to make an OALayoutGuide class that's nothing more than a UIView backed with a CATransformLayer