Authored by Jonas Budelmann

remove ability to chain equality, less ambiguous if you need to reference constr…

…aint for animation or updating later on
... ... @@ -158,12 +158,8 @@
[self.delegate addConstraint:self];
self.added = YES;
}
for (id<MASConstraint> constraint in self.currentChildConstraints.copy) {
id<MASConstraint> newConstraint = block(constraint, attr);
if (newConstraint != constraint) {
[self.currentChildConstraints removeObject:constraint];
[self.currentChildConstraints addObject:newConstraint];
}
for (id<MASConstraint> constraint in self.currentChildConstraints) {
block(constraint, attr);
}
return self;
};
... ... @@ -199,7 +195,6 @@
for (id<MASConstraint> constraint in self.completedChildConstraints) {
[constraint commit];
}
[self.currentChildConstraints removeAllObjects];
[self.completedChildConstraints removeAllObjects];
}
... ...
... ... @@ -63,18 +63,6 @@
}
}
- (instancetype)cloneIfNeeded {
if (self.hasLayoutRelation) {
MASViewAttribute *firstViewAttribute = [[MASViewAttribute alloc] initWithView:self.firstViewAttribute.view layoutAttribute:self.firstViewAttribute.layoutAttribute];
MASViewConstraint *viewConstraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:firstViewAttribute];
viewConstraint.delegate = self.delegate;
viewConstraint.layoutRelation = self.layoutRelation;
return viewConstraint;
}
return self;
}
#pragma mark - NSLayoutConstraint constant proxies
- (id<MASConstraint> (^)(UIEdgeInsets))insets {
... ... @@ -190,40 +178,34 @@
- (id<MASConstraint> (^)(id))equalTo {
return ^id(id attr) {
NSAssert(!self.hasBeenCommitted,
@"Cannot modify constraint equal relation after it has been committed");
NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation");
MASViewConstraint *viewConstraint = [self cloneIfNeeded];
viewConstraint.layoutRelation = NSLayoutRelationEqual;
viewConstraint.secondViewAttribute = attr;
[viewConstraint.delegate addConstraint:viewConstraint];
return viewConstraint;
self.layoutRelation = NSLayoutRelationEqual;
self.secondViewAttribute = attr;
[self.delegate addConstraint:self];
return self;
};
}
- (id<MASConstraint> (^)(id))greaterThanOrEqualTo {
return ^id(id attr) {
NSAssert(!self.hasBeenCommitted,
@"Cannot modify constraint greaterThanOrEqual relation after it has been committed");
NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation");
MASViewConstraint *viewConstraint = [self cloneIfNeeded];
viewConstraint.layoutRelation = NSLayoutRelationGreaterThanOrEqual;
viewConstraint.secondViewAttribute = attr;
[viewConstraint.delegate addConstraint:viewConstraint];
return viewConstraint;
self.layoutRelation = NSLayoutRelationGreaterThanOrEqual;
self.secondViewAttribute = attr;
[self.delegate addConstraint:self];
return self;
};
}
- (id<MASConstraint> (^)(id))lessThanOrEqualTo {
return ^id(id attr) {
NSAssert(!self.hasBeenCommitted,
@"Cannot modify constraint lessThanOrEqual relation after it has been committed");
NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation");
MASViewConstraint *viewConstraint = [self cloneIfNeeded];
viewConstraint.layoutRelation = NSLayoutRelationLessThanOrEqual;
viewConstraint.secondViewAttribute = attr;
[viewConstraint.delegate addConstraint:viewConstraint];
return viewConstraint;
self.layoutRelation = NSLayoutRelationLessThanOrEqual;
self.secondViewAttribute = attr;
[self.delegate addConstraint:self];
return self;
};
}
... ...
... ... @@ -49,7 +49,6 @@
[self.animatableConstraints addObjectsFromArray:@[
make.edges.equalTo(superview).insets(paddingInsets).priorityLow(),
make.bottom.equalTo(view3.mas_top).offset(-padding),
make.right.equalTo(view2.mas_left).offset(-padding),
]];
make.size.equalTo(view2);
... ... @@ -70,11 +69,8 @@
[view3 mas_makeConstraints:^(MASConstraintMaker *make) {
[self.animatableConstraints addObjectsFromArray:@[
make.edges.equalTo(superview).insets(paddingInsets).priorityLow(),
make.top.equalTo(view1.mas_bottom).offset(padding),
]];
//TODO or pass an array
//constraints.height.equal(superview.subviews);
make.height.equalTo(view1.mas_height);
make.height.equalTo(view2.mas_height);
}];
... ... @@ -83,6 +79,7 @@
}
- (void)didMoveToSuperview {
[self layoutIfNeeded];
[self startAnimatingWithInvertedInsets:NO];
}
... ...
... ... @@ -43,11 +43,9 @@
make.bottom.equalTo(view3.top).offset(-padding);
make.right.equalTo(view2.left).offset(-padding);
make.width.equalTo(view2.width);
//you can chain same attribute
make.height
.equalTo(view2.height)
.equalTo(view3.height);
make.height.equalTo(view2.height);
make.height.equalTo(view3.height);
}];
//with is semantic and option
... ... @@ -58,7 +56,6 @@
make.right.equalTo(superview.mas_right).offset(-padding);
make.width.equalTo(view1.mas_width);
//or define it multiple times
make.height.equalTo(view1.mas_height);
make.height.equalTo(view3.mas_height);
}];
... ... @@ -69,12 +66,10 @@
make.bottom.equalTo(superview.mas_bottom).offset(-padding);
make.right.equalTo(superview.mas_right).offset(-padding);
//TODO or pass an array
//constraints.height.equal(superview.subviews);
make.height.equalTo(view1.mas_height);
make.height.equalTo(view2.mas_height);
}];
return self;
}
... ...
... ... @@ -20,6 +20,7 @@
@interface MASViewConstraint ()
@property (nonatomic, assign) CGFloat layoutConstant;
@property (nonatomic, assign) MASLayoutPriority layoutPriority;
@end
... ... @@ -100,9 +101,7 @@ it(@"should complete children", ^{
//first equality statement
composite.equalTo(newView).sizeOffset(CGSizeMake(90, 30));
[verify(delegate) addConstraint:(id)composite];
expect(composite.completedChildConstraints).to.haveCountOf(2);
expect(composite.currentChildConstraints).to.haveCountOf(2);
... ... @@ -110,38 +109,20 @@ it(@"should complete children", ^{
expect(viewConstraint.secondViewAttribute.view).to.beIdenticalTo(newView);
expect(viewConstraint.secondViewAttribute.layoutAttribute).to.equal(NSLayoutAttributeWidth);
expect(viewConstraint.layoutConstant).to.equal(90);
expect(viewConstraint.layoutPriority).to.equal(MASLayoutPriorityRequired);
viewConstraint = composite.completedChildConstraints[1];
expect(viewConstraint.secondViewAttribute.view).to.beIdenticalTo(newView);
expect(viewConstraint.secondViewAttribute.layoutAttribute).to.equal(NSLayoutAttributeHeight);
expect(viewConstraint.layoutConstant).to.equal(30);
expect(viewConstraint.layoutPriority).to.equal(MASLayoutPriorityRequired);
//chain another equality statement
composite.greaterThanOrEqualTo(@6);
expect(composite.completedChildConstraints).to.haveCountOf(4);
expect(composite.currentChildConstraints).to.haveCountOf(2);
viewConstraint = composite.completedChildConstraints[2];
expect(viewConstraint.secondViewAttribute.view).to.beNil();
expect(viewConstraint.secondViewAttribute.layoutAttribute).to.equal(0);
expect(viewConstraint.layoutConstant).to.equal(6);
viewConstraint = composite.completedChildConstraints[2];
expect(viewConstraint.secondViewAttribute.view).to.beNil();
expect(viewConstraint.secondViewAttribute.layoutAttribute).to.equal(0);
expect(viewConstraint.layoutConstant).to.equal(6);
//still referencing same view
viewConstraint = composite.currentChildConstraints[0];
expect(viewConstraint.firstViewAttribute.view).to.beIdenticalTo(composite.view);
expect(viewConstraint.firstViewAttribute.layoutAttribute).to.equal(NSLayoutAttributeWidth);
viewConstraint = composite.currentChildConstraints[1];
expect(viewConstraint.firstViewAttribute.view).to.beIdenticalTo(composite.view);
expect(viewConstraint.firstViewAttribute.layoutAttribute).to.equal(NSLayoutAttributeHeight);
//new current
expect(composite.completedChildConstraints[0]).to.beIdenticalTo(composite.currentChildConstraints[0]);
expect(composite.completedChildConstraints[1]).to.beIdenticalTo(composite.currentChildConstraints[1]);
});
it(@"should remove all on commit", ^{
it(@"should remove completed on commit", ^{
composite = [[MASCompositeConstraint alloc] initWithView:view type:MASCompositeViewConstraintTypeSize];
composite.delegate = delegate;
UIView *newView = UIView.new;
... ... @@ -158,7 +139,7 @@ it(@"should remove all on commit", ^{
[composite commit];
expect(composite.completedChildConstraints).to.haveCountOf(0);
expect(composite.currentChildConstraints).to.haveCountOf(0);
expect(composite.currentChildConstraints).to.haveCountOf(2);
});
SpecEnd
\ No newline at end of file
... ...
... ... @@ -43,9 +43,9 @@ beforeEach(^{
[superview addSubview:otherView];
});
describe(@"equality chaining", ^{
describe(@"create equality constraint", ^{
it(@"should return same constraint when encountering equal for first time", ^{
it(@"should create equal constraint", ^{
MASViewAttribute *secondViewAttribute = otherView.mas_top;
MASViewConstraint *newConstraint = constraint.equalTo(secondViewAttribute);
... ... @@ -55,17 +55,7 @@ describe(@"equality chaining", ^{
expect(constraint.layoutRelation).to.equal(NSLayoutRelationEqual);
});
it(@"should start new constraint when encountering equal subsequently", ^{
MASViewAttribute *secondViewAttribute = otherView.mas_top;
constraint.greaterThanOrEqualTo(secondViewAttribute);
MASViewConstraint *newConstraint = constraint.equalTo(secondViewAttribute);
[verify(constraint.delegate) addConstraint:(id)constraint];
[verify(constraint.delegate) addConstraint:(id)newConstraint];
expect(newConstraint).notTo.beIdenticalTo(constraint);
});
it(@"should return same constraint when encountering greaterThanOrEqual for first time", ^{
it(@"should create greaterThanOrEqual constraint", ^{
MASViewAttribute *secondViewAttribute = otherView.mas_top;
MASViewConstraint *newConstraint = constraint.greaterThanOrEqualTo(secondViewAttribute);
... ... @@ -75,17 +65,7 @@ describe(@"equality chaining", ^{
expect(constraint.layoutRelation).to.equal(NSLayoutRelationGreaterThanOrEqual);
});
it(@"should start new constraint when encountering greaterThanOrEqual subsequently", ^{
MASViewAttribute *secondViewAttribute = otherView.mas_top;
constraint.lessThanOrEqualTo(secondViewAttribute);
MASViewConstraint *newConstraint = constraint.greaterThanOrEqualTo(secondViewAttribute);
[verify(constraint.delegate) addConstraint:(id)constraint];
[verify(constraint.delegate) addConstraint:(id)newConstraint];
expect(newConstraint).notTo.beIdenticalTo(constraint);
});
it(@"should return same constraint when encountering lessThanOrEqual for first time", ^{
it(@"create lessThanOrEqual constraint", ^{
MASViewAttribute *secondViewAttribute = otherView.mas_top;
MASViewConstraint *newConstraint = constraint.lessThanOrEqualTo(secondViewAttribute);
... ... @@ -95,37 +75,27 @@ describe(@"equality chaining", ^{
expect(constraint.layoutRelation).to.equal(NSLayoutRelationLessThanOrEqual);
});
it(@"should start new constraint when encountering lessThanOrEqual subsequently", ^{
it(@"should not allow update of equal", ^{
MASViewAttribute *secondViewAttribute = otherView.mas_top;
constraint.equalTo(secondViewAttribute);
MASViewConstraint *newConstraint = constraint.lessThanOrEqualTo(secondViewAttribute);
[verify(constraint.delegate) addConstraint:(id)constraint];
[verify(constraint.delegate) addConstraint:(id)newConstraint];
expect(newConstraint).notTo.beIdenticalTo(constraint);
});
it(@"should not allow update of equal once layoutconstraint is created", ^{
MASViewAttribute *secondViewAttribute = otherView.mas_top;
[constraint commit];
constraint.lessThanOrEqualTo(secondViewAttribute);
expect(^{
constraint.equalTo(secondViewAttribute);
}).to.raise(@"NSInternalInconsistencyException");
});
it(@"should not allow update of lessThanOrEqual once layoutconstraint is created", ^{
it(@"should not allow update of lessThanOrEqual", ^{
MASViewAttribute *secondViewAttribute = otherView.mas_top;
[constraint commit];
constraint.equalTo(secondViewAttribute);
expect(^{
constraint.lessThanOrEqualTo(secondViewAttribute);
}).to.raise(@"NSInternalInconsistencyException");
});
it(@"should not allow update of greaterThanOrEqual once layoutconstraint is created", ^{
it(@"should not allow update of greaterThanOrEqual", ^{
MASViewAttribute *secondViewAttribute = otherView.mas_top;
[constraint commit];
constraint.greaterThanOrEqualTo(secondViewAttribute);
expect(^{
constraint.greaterThanOrEqualTo(secondViewAttribute);
... ...
... ... @@ -114,7 +114,6 @@ if you want view.left to be greater than or equal to label.left :
```obj-c
//these two constraints are exactly the same
make.left.greaterThanOrEqualTo(label);
make.left.greaterThanOrEqualTo(label.mas_left);
```
... ... @@ -123,9 +122,8 @@ make.left.greaterThanOrEqualTo(label.mas_left);
if you want to set view to have a minimum and maximum width you could pass a number to the equality blocks:
```obj-c
make.width
.greaterThanOrEqualTo(@200)
.lessThanOrEqualTo(@400)
make.width.greaterThanOrEqualTo(@200);
make.width.lessThanOrEqualTo(@400)
```
## Learn to prioritize
... ...