Authored by Jonas Budelmann

accept array in equality blocks

1 Pod::Spec.new do |s| 1 Pod::Spec.new do |s|
2 s.name = 'Masonry' 2 s.name = 'Masonry'
3 - s.version = '0.0.4' 3 + s.version = '0.1.0'
4 s.license = 'MIT' 4 s.license = 'MIT'
5 s.summary = 'A light-weight layout framework which makes creating iOS AutoLayout NSLayoutConstraints in code quick, readable and descriptive.' 5 s.summary = 'A light-weight layout framework which makes creating iOS AutoLayout NSLayoutConstraints in code quick, readable and descriptive.'
6 s.homepage = 'https://github.com/cloudkite/Masonry' 6 s.homepage = 'https://github.com/cloudkite/Masonry'
7 s.author = { 'Jonas Budelmann' => 'jonas.budelmann@gmail.com' } 7 s.author = { 'Jonas Budelmann' => 'jonas.budelmann@gmail.com' }
8 8
9 - s.source = { :git => 'https://github.com/cloudkite/Masonry.git', :tag => 'v0.0.4' } 9 + s.source = { :git => 'https://github.com/cloudkite/Masonry.git', :tag => 'v0.1.0' }
10 10
11 s.description = %{ 11 s.description = %{
12 Masonary is a light-weight layout framework which wraps AutoLayout with a nicer syntax. 12 Masonary is a light-weight layout framework which wraps AutoLayout with a nicer syntax.
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 objects = { 7 objects = {
8 8
9 /* Begin PBXBuildFile section */ 9 /* Begin PBXBuildFile section */
  10 + DD38397E17A5170F00C35C17 /* MASConstraintDelegateMock.m in Sources */ = {isa = PBXBuildFile; fileRef = DD38397D17A5170F00C35C17 /* MASConstraintDelegateMock.m */; };
10 DD52F1AE179CA93B005CD195 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD52F1AD179CA93B005CD195 /* Foundation.framework */; }; 11 DD52F1AE179CA93B005CD195 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD52F1AD179CA93B005CD195 /* Foundation.framework */; };
11 DD52F1BD179CA93B005CD195 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD52F1BC179CA93B005CD195 /* SenTestingKit.framework */; }; 12 DD52F1BD179CA93B005CD195 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD52F1BC179CA93B005CD195 /* SenTestingKit.framework */; };
12 DD52F1BF179CA93B005CD195 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD52F1BE179CA93B005CD195 /* UIKit.framework */; }; 13 DD52F1BF179CA93B005CD195 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD52F1BE179CA93B005CD195 /* UIKit.framework */; };
@@ -55,6 +56,8 @@ @@ -55,6 +56,8 @@
55 56
56 /* Begin PBXFileReference section */ 57 /* Begin PBXFileReference section */
57 CC61B4599FE44F12AD607E9B /* Pods-MasonryTests.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MasonryTests.xcconfig"; path = "Pods/Pods-MasonryTests.xcconfig"; sourceTree = SOURCE_ROOT; }; 58 CC61B4599FE44F12AD607E9B /* Pods-MasonryTests.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MasonryTests.xcconfig"; path = "Pods/Pods-MasonryTests.xcconfig"; sourceTree = SOURCE_ROOT; };
  59 + DD38397C17A5170F00C35C17 /* MASConstraintDelegateMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASConstraintDelegateMock.h; sourceTree = "<group>"; };
  60 + DD38397D17A5170F00C35C17 /* MASConstraintDelegateMock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASConstraintDelegateMock.m; sourceTree = "<group>"; };
58 DD52F1AA179CA93B005CD195 /* libMasonry.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMasonry.a; sourceTree = BUILT_PRODUCTS_DIR; }; 61 DD52F1AA179CA93B005CD195 /* libMasonry.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMasonry.a; sourceTree = BUILT_PRODUCTS_DIR; };
59 DD52F1AD179CA93B005CD195 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 62 DD52F1AD179CA93B005CD195 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
60 DD52F1B1179CA93B005CD195 /* Masonry-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Masonry-Prefix.pch"; sourceTree = "<group>"; }; 63 DD52F1B1179CA93B005CD195 /* Masonry-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Masonry-Prefix.pch"; sourceTree = "<group>"; };
@@ -168,6 +171,8 @@ @@ -168,6 +171,8 @@
168 DD52F1C5179CA93B005CD195 /* Supporting Files */ = { 171 DD52F1C5179CA93B005CD195 /* Supporting Files */ = {
169 isa = PBXGroup; 172 isa = PBXGroup;
170 children = ( 173 children = (
  174 + DD38397C17A5170F00C35C17 /* MASConstraintDelegateMock.h */,
  175 + DD38397D17A5170F00C35C17 /* MASConstraintDelegateMock.m */,
171 DD52F1D6179CAA71005CD195 /* MasonryTests-Prefix.pch */, 176 DD52F1D6179CAA71005CD195 /* MasonryTests-Prefix.pch */,
172 DD52F1C6179CA93B005CD195 /* MasonryTests-Info.plist */, 177 DD52F1C6179CA93B005CD195 /* MasonryTests-Info.plist */,
173 DD52F1C7179CA93B005CD195 /* InfoPlist.strings */, 178 DD52F1C7179CA93B005CD195 /* InfoPlist.strings */,
@@ -371,6 +376,7 @@ @@ -371,6 +376,7 @@
371 files = ( 376 files = (
372 DD52F1DA179CAA9C005CD195 /* MASCompositeConstraintSpec.m in Sources */, 377 DD52F1DA179CAA9C005CD195 /* MASCompositeConstraintSpec.m in Sources */,
373 DD52F1DB179CAA9C005CD195 /* MASViewConstraintSpec.m in Sources */, 378 DD52F1DB179CAA9C005CD195 /* MASViewConstraintSpec.m in Sources */,
  379 + DD38397E17A5170F00C35C17 /* MASConstraintDelegateMock.m in Sources */,
374 ); 380 );
375 runOnlyForDeploymentPostprocessing = 0; 381 runOnlyForDeploymentPostprocessing = 0;
376 }; 382 };
@@ -9,18 +9,19 @@ @@ -9,18 +9,19 @@
9 #import <UIKit/UIKit.h> 9 #import <UIKit/UIKit.h>
10 #import "MASConstraint.h" 10 #import "MASConstraint.h"
11 11
12 -typedef NS_ENUM(NSInteger, MASCompositeViewConstraintType) {  
13 - MASCompositeViewConstraintTypeEdges, //top, left, bottom, right  
14 - MASCompositeViewConstraintTypeSize, //width, height  
15 - MASCompositeViewConstraintTypeCenter, //centerX, centerY 12 +typedef NS_ENUM(NSInteger, MASCompositeConstraintType) {
  13 + MASCompositeConstraintTypeEdges, //top, left, bottom, right
  14 + MASCompositeConstraintTypeSize, //width, height
  15 + MASCompositeConstraintTypeCenter, //centerX, centerY
16 }; 16 };
17 17
18 @interface MASCompositeConstraint : NSObject <MASConstraint> 18 @interface MASCompositeConstraint : NSObject <MASConstraint>
19 19
20 @property (nonatomic, weak) id<MASConstraintDelegate> delegate; 20 @property (nonatomic, weak) id<MASConstraintDelegate> delegate;
21 @property (nonatomic, weak, readonly) UIView *view; 21 @property (nonatomic, weak, readonly) UIView *view;
22 -@property (nonatomic, assign, readonly) MASCompositeViewConstraintType type; 22 +@property (nonatomic, assign, readonly) MASCompositeConstraintType type;
23 23
24 -- (id)initWithView:(UIView *)view type:(MASCompositeViewConstraintType)type; 24 +- (id)initWithView:(UIView *)view type:(MASCompositeConstraintType)type;
  25 +- (id)initWithView:(UIView *)view children:(NSArray *)children;
25 26
26 @end 27 @end
@@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
18 18
19 @implementation MASCompositeConstraint 19 @implementation MASCompositeConstraint
20 20
21 -- (id)initWithView:(UIView *)view type:(MASCompositeViewConstraintType)type { 21 +- (id)initWithView:(UIView *)view type:(MASCompositeConstraintType)type {
22 self = [super init]; 22 self = [super init];
23 if (!self) return nil; 23 if (!self) return nil;
24 24
@@ -30,23 +30,33 @@ @@ -30,23 +30,33 @@
30 return self; 30 return self;
31 } 31 }
32 32
  33 +- (id)initWithView:(UIView *)view children:(NSArray *)children {
  34 + self = [super init];
  35 + if (!self) return nil;
  36 +
  37 + _view = view;
  38 + _childConstraints = [children mutableCopy];
  39 +
  40 + return self;
  41 +}
  42 +
33 - (void)createChildren { 43 - (void)createChildren {
34 self.childConstraints = NSMutableArray.array; 44 self.childConstraints = NSMutableArray.array;
35 45
36 NSArray *viewAttributes; 46 NSArray *viewAttributes;
37 switch (self.type) { 47 switch (self.type) {
38 - case MASCompositeViewConstraintTypeEdges: 48 + case MASCompositeConstraintTypeEdges:
39 viewAttributes = @[ 49 viewAttributes = @[
40 self.view.mas_top, self.view.mas_left, 50 self.view.mas_top, self.view.mas_left,
41 self.view.mas_bottom, self.view.mas_right 51 self.view.mas_bottom, self.view.mas_right
42 ]; 52 ];
43 break; 53 break;
44 - case MASCompositeViewConstraintTypeSize: 54 + case MASCompositeConstraintTypeSize:
45 viewAttributes = @[ 55 viewAttributes = @[
46 self.view.mas_width, self.view.mas_height 56 self.view.mas_width, self.view.mas_height
47 ]; 57 ];
48 break; 58 break;
49 - case MASCompositeViewConstraintTypeCenter: 59 + case MASCompositeConstraintTypeCenter:
50 viewAttributes = @[ 60 viewAttributes = @[
51 self.view.mas_centerX, self.view.mas_centerY 61 self.view.mas_centerX, self.view.mas_centerY
52 ]; 62 ];
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 // Copyright (c) 2013 cloudling. All rights reserved. 6 // Copyright (c) 2013 cloudling. All rights reserved.
7 // 7 //
8 8
9 -#import <Foundation/Foundation.h> 9 +#import <UIKit/UIKit.h>
10 10
11 enum { 11 enum {
12 MASLayoutPriorityRequired = UILayoutPriorityRequired, 12 MASLayoutPriorityRequired = UILayoutPriorityRequired,
@@ -102,19 +102,19 @@ @@ -102,19 +102,19 @@
102 #pragma mark - composite Attributes 102 #pragma mark - composite Attributes
103 103
104 - (id<MASConstraint>)edges { 104 - (id<MASConstraint>)edges {
105 - MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithView:self.view type:MASCompositeViewConstraintTypeEdges]; 105 + MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithView:self.view type:MASCompositeConstraintTypeEdges];
106 constraint.delegate = self; 106 constraint.delegate = self;
107 return constraint; 107 return constraint;
108 } 108 }
109 109
110 - (id<MASConstraint>)size { 110 - (id<MASConstraint>)size {
111 - MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithView:self.view type:MASCompositeViewConstraintTypeSize]; 111 + MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithView:self.view type:MASCompositeConstraintTypeSize];
112 constraint.delegate = self; 112 constraint.delegate = self;
113 return constraint; 113 return constraint;
114 } 114 }
115 115
116 - (id<MASConstraint>)center { 116 - (id<MASConstraint>)center {
117 - MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithView:self.view type:MASCompositeViewConstraintTypeCenter]; 117 + MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithView:self.view type:MASCompositeConstraintTypeCenter];
118 constraint.delegate = self; 118 constraint.delegate = self;
119 return constraint; 119 return constraint;
120 } 120 }
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 #import "MASViewAttribute.h" 9 #import "MASViewAttribute.h"
10 #import "MASConstraint.h" 10 #import "MASConstraint.h"
11 11
12 -@interface MASViewConstraint : NSObject <MASConstraint> 12 +@interface MASViewConstraint : NSObject <MASConstraint, NSCopying>
13 13
14 @property (nonatomic, weak) id<MASConstraintDelegate> delegate; 14 @property (nonatomic, weak) id<MASConstraintDelegate> delegate;
15 @property (nonatomic, strong, readonly) MASViewAttribute *firstViewAttribute; 15 @property (nonatomic, strong, readonly) MASViewAttribute *firstViewAttribute;
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 // 7 //
8 8
9 #import "MASViewConstraint.h" 9 #import "MASViewConstraint.h"
  10 +#import "MASCompositeConstraint.h"
10 11
11 @interface MASViewConstraint () 12 @interface MASViewConstraint ()
12 13
@@ -33,6 +34,18 @@ @@ -33,6 +34,18 @@
33 return self; 34 return self;
34 } 35 }
35 36
  37 +#pragma mark - NSCoping
  38 +
  39 +- (id)copyWithZone:(NSZone *)zone {
  40 + MASViewConstraint *constraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:self.firstViewAttribute];
  41 + constraint.layoutConstant = self.layoutConstant;
  42 + constraint.layoutRelation = self.layoutRelation;
  43 + constraint.layoutPriority = self.layoutPriority;
  44 + constraint.layoutMultiplier = self.layoutMultiplier;
  45 + constraint.delegate = self.delegate;
  46 + return constraint;
  47 +}
  48 +
36 #pragma mark - private 49 #pragma mark - private
37 50
38 - (void)setLayoutConstant:(CGFloat)layoutConstant { 51 - (void)setLayoutConstant:(CGFloat)layoutConstant {
@@ -52,9 +65,7 @@ @@ -52,9 +65,7 @@
52 - (void)setSecondViewAttribute:(id)secondViewAttribute { 65 - (void)setSecondViewAttribute:(id)secondViewAttribute {
53 if ([secondViewAttribute isKindOfClass:NSNumber.class]) { 66 if ([secondViewAttribute isKindOfClass:NSNumber.class]) {
54 self.layoutConstant = [secondViewAttribute doubleValue]; 67 self.layoutConstant = [secondViewAttribute doubleValue];
55 -// } else if ([secondViewAttribute isKindOfClass:NSArray.class]) {  
56 -// //TODO Composite  
57 - } else if ([secondViewAttribute isKindOfClass:UIView.class]) { 68 + } else if ([secondViewAttribute isKindOfClass:UIView.class]) {
58 _secondViewAttribute = [[MASViewAttribute alloc] initWithView:secondViewAttribute layoutAttribute:self.firstViewAttribute.layoutAttribute]; 69 _secondViewAttribute = [[MASViewAttribute alloc] initWithView:secondViewAttribute layoutAttribute:self.firstViewAttribute.layoutAttribute];
59 } else if ([secondViewAttribute isKindOfClass:MASViewAttribute.class]) { 70 } else if ([secondViewAttribute isKindOfClass:MASViewAttribute.class]) {
60 _secondViewAttribute = secondViewAttribute; 71 _secondViewAttribute = secondViewAttribute;
@@ -176,37 +187,39 @@ @@ -176,37 +187,39 @@
176 187
177 #pragma mark - NSLayoutRelation proxies 188 #pragma mark - NSLayoutRelation proxies
178 189
179 -- (id<MASConstraint> (^)(id))equalTo {  
180 - return ^id(id attr) { 190 +- (id<MASConstraint> (^)(id))equalityWithRelation:(NSLayoutRelation)relation {
  191 + return ^id(id attribute) {
181 NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation"); 192 NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation");
182 -  
183 - self.layoutRelation = NSLayoutRelationEqual;  
184 - self.secondViewAttribute = attr;  
185 - [self.delegate addConstraint:self];  
186 - return self; 193 + if ([attribute isKindOfClass:NSArray.class]) {
  194 + NSMutableArray *children = NSMutableArray.new;
  195 + for (id attr in attribute) {
  196 + MASViewConstraint *viewConstraint = [self copy];
  197 + viewConstraint.secondViewAttribute = attr;
  198 + [viewConstraint.delegate addConstraint:viewConstraint];
  199 + [children addObject:viewConstraint];
  200 + }
  201 + MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithView:self.firstViewAttribute.view children:children];
  202 + compositeConstraint.delegate = self.delegate;
  203 + return compositeConstraint;
  204 + } else {
  205 + self.layoutRelation = relation;
  206 + self.secondViewAttribute = attribute;
  207 + [self.delegate addConstraint:self];
  208 + return self;
  209 + }
187 }; 210 };
188 } 211 }
189 212
  213 +- (id<MASConstraint> (^)(id))equalTo {
  214 + return [self equalityWithRelation:NSLayoutRelationEqual];
  215 +}
  216 +
190 - (id<MASConstraint> (^)(id))greaterThanOrEqualTo { 217 - (id<MASConstraint> (^)(id))greaterThanOrEqualTo {
191 - return ^id(id attr) {  
192 - NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation");  
193 -  
194 - self.layoutRelation = NSLayoutRelationGreaterThanOrEqual;  
195 - self.secondViewAttribute = attr;  
196 - [self.delegate addConstraint:self];  
197 - return self;  
198 - }; 218 + return [self equalityWithRelation:NSLayoutRelationGreaterThanOrEqual];
199 } 219 }
200 220
201 - (id<MASConstraint> (^)(id))lessThanOrEqualTo { 221 - (id<MASConstraint> (^)(id))lessThanOrEqualTo {
202 - return ^id(id attr) {  
203 - NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation");  
204 -  
205 - self.layoutRelation = NSLayoutRelationLessThanOrEqual;  
206 - self.secondViewAttribute = attr;  
207 - [self.delegate addConstraint:self];  
208 - return self;  
209 - }; 222 + return [self equalityWithRelation:NSLayoutRelationLessThanOrEqual];
210 } 223 }
211 224
212 #pragma mark - Semantic properties 225 #pragma mark - Semantic properties
@@ -56,8 +56,7 @@ @@ -56,8 +56,7 @@
56 make.right.equalTo(superview.mas_right).offset(-padding); 56 make.right.equalTo(superview.mas_right).offset(-padding);
57 make.width.equalTo(view1.mas_width); 57 make.width.equalTo(view1.mas_width);
58 58
59 - make.height.equalTo(view1.mas_height);  
60 - make.height.equalTo(view3.mas_height); 59 + make.height.equalTo(@[view1, view3]); //can pass array of views
61 }]; 60 }];
62 61
63 [view3 mas_makeConstraints:^(MASConstraintMaker *make) { 62 [view3 mas_makeConstraints:^(MASConstraintMaker *make) {
@@ -66,8 +65,7 @@ @@ -66,8 +65,7 @@
66 make.bottom.equalTo(superview.mas_bottom).offset(-padding); 65 make.bottom.equalTo(superview.mas_bottom).offset(-padding);
67 make.right.equalTo(superview.mas_right).offset(-padding); 66 make.right.equalTo(superview.mas_right).offset(-padding);
68 67
69 - make.height.equalTo(view1.mas_height);  
70 - make.height.equalTo(view2.mas_height); 68 + make.height.equalTo(@[view1.mas_height, view2.mas_height]); //can pass array of attributes
71 }]; 69 }];
72 70
73 return self; 71 return self;
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 8
9 #import "MASCompositeConstraint.h" 9 #import "MASCompositeConstraint.h"
10 #import "MASViewConstraint.h" 10 #import "MASViewConstraint.h"
  11 +#import "MASConstraintDelegateMock.h"
11 12
12 @interface MASCompositeConstraint () <MASConstraintDelegate> 13 @interface MASCompositeConstraint () <MASConstraintDelegate>
13 14
@@ -24,21 +25,21 @@ @@ -24,21 +25,21 @@
24 25
25 SpecBegin(MASCompositeConstraint) 26 SpecBegin(MASCompositeConstraint)
26 27
27 -__block id<MASConstraintDelegate> delegate; 28 +__block MASConstraintDelegateMock *delegate;
28 __block UIView *superview; 29 __block UIView *superview;
29 __block UIView *view; 30 __block UIView *view;
30 __block MASCompositeConstraint *composite; 31 __block MASCompositeConstraint *composite;
31 32
32 beforeEach(^{ 33 beforeEach(^{
33 composite = nil; 34 composite = nil;
34 - delegate = mockProtocol(@protocol(MASConstraintDelegate)); 35 + delegate = MASConstraintDelegateMock.new;
35 view = UIView.new; 36 view = UIView.new;
36 superview = UIView.new; 37 superview = UIView.new;
37 [superview addSubview:view]; 38 [superview addSubview:view];
38 }); 39 });
39 40
40 it(@"should create centerY and centerX children", ^{ 41 it(@"should create centerY and centerX children", ^{
41 - composite = [[MASCompositeConstraint alloc] initWithView:view type:MASCompositeViewConstraintTypeCenter]; 42 + composite = [[MASCompositeConstraint alloc] initWithView:view type:MASCompositeConstraintTypeCenter];
42 43
43 expect(composite.childConstraints).to.haveCountOf(2); 44 expect(composite.childConstraints).to.haveCountOf(2);
44 45
@@ -53,7 +54,7 @@ it(@"should create centerY and centerX children", ^{ @@ -53,7 +54,7 @@ it(@"should create centerY and centerX children", ^{
53 54
54 it(@"should create top, left, bottom, right children", ^{ 55 it(@"should create top, left, bottom, right children", ^{
55 UIView *newView = UIView.new; 56 UIView *newView = UIView.new;
56 - composite = [[MASCompositeConstraint alloc] initWithView:view type:MASCompositeViewConstraintTypeEdges]; 57 + composite = [[MASCompositeConstraint alloc] initWithView:view type:MASCompositeConstraintTypeEdges];
57 composite.equalTo(newView); 58 composite.equalTo(newView);
58 59
59 expect(composite.childConstraints).to.haveCountOf(4); 60 expect(composite.childConstraints).to.haveCountOf(4);
@@ -80,7 +81,7 @@ it(@"should create top, left, bottom, right children", ^{ @@ -80,7 +81,7 @@ it(@"should create top, left, bottom, right children", ^{
80 }); 81 });
81 82
82 it(@"should create width and height children", ^{ 83 it(@"should create width and height children", ^{
83 - composite = [[MASCompositeConstraint alloc] initWithView:view type:MASCompositeViewConstraintTypeSize]; 84 + composite = [[MASCompositeConstraint alloc] initWithView:view type:MASCompositeConstraintTypeSize];
84 expect(composite.childConstraints).to.haveCountOf(2); 85 expect(composite.childConstraints).to.haveCountOf(2);
85 86
86 MASViewConstraint *viewConstraint = composite.childConstraints[0]; 87 MASViewConstraint *viewConstraint = composite.childConstraints[0];
@@ -93,12 +94,12 @@ it(@"should create width and height children", ^{ @@ -93,12 +94,12 @@ it(@"should create width and height children", ^{
93 }); 94 });
94 95
95 it(@"should complete children", ^{ 96 it(@"should complete children", ^{
96 - composite = [[MASCompositeConstraint alloc] initWithView:view type:MASCompositeViewConstraintTypeSize]; 97 + composite = [[MASCompositeConstraint alloc] initWithView:view type:MASCompositeConstraintTypeSize];
97 composite.delegate = delegate; 98 composite.delegate = delegate;
98 UIView *newView = UIView.new; 99 UIView *newView = UIView.new;
99 100
100 //first equality statement 101 //first equality statement
101 - composite.equalTo(newView).sizeOffset(CGSizeMake(90, 30)); 102 + composite.equalTo(newView).sizeOffset(CGSizeMake(90, 30)).priorityLow();
102 103
103 expect(composite.childConstraints).to.haveCountOf(2); 104 expect(composite.childConstraints).to.haveCountOf(2);
104 105
@@ -106,17 +107,17 @@ it(@"should complete children", ^{ @@ -106,17 +107,17 @@ it(@"should complete children", ^{
106 expect(viewConstraint.secondViewAttribute.view).to.beIdenticalTo(newView); 107 expect(viewConstraint.secondViewAttribute.view).to.beIdenticalTo(newView);
107 expect(viewConstraint.secondViewAttribute.layoutAttribute).to.equal(NSLayoutAttributeWidth); 108 expect(viewConstraint.secondViewAttribute.layoutAttribute).to.equal(NSLayoutAttributeWidth);
108 expect(viewConstraint.layoutConstant).to.equal(90); 109 expect(viewConstraint.layoutConstant).to.equal(90);
109 - expect(viewConstraint.layoutPriority).to.equal(MASLayoutPriorityRequired); 110 + expect(viewConstraint.layoutPriority).to.equal(MASLayoutPriorityDefaultLow);
110 111
111 viewConstraint = composite.childConstraints[1]; 112 viewConstraint = composite.childConstraints[1];
112 expect(viewConstraint.secondViewAttribute.view).to.beIdenticalTo(newView); 113 expect(viewConstraint.secondViewAttribute.view).to.beIdenticalTo(newView);
113 expect(viewConstraint.secondViewAttribute.layoutAttribute).to.equal(NSLayoutAttributeHeight); 114 expect(viewConstraint.secondViewAttribute.layoutAttribute).to.equal(NSLayoutAttributeHeight);
114 expect(viewConstraint.layoutConstant).to.equal(30); 115 expect(viewConstraint.layoutConstant).to.equal(30);
115 - expect(viewConstraint.layoutPriority).to.equal(MASLayoutPriorityRequired); 116 + expect(viewConstraint.layoutPriority).to.equal(MASLayoutPriorityDefaultLow);
116 }); 117 });
117 118
118 -it(@"should remove completed on commit", ^{  
119 - composite = [[MASCompositeConstraint alloc] initWithView:view type:MASCompositeViewConstraintTypeSize]; 119 +it(@"should not remove on commit", ^{
  120 + composite = [[MASCompositeConstraint alloc] initWithView:view type:MASCompositeConstraintTypeSize];
120 composite.delegate = delegate; 121 composite.delegate = delegate;
121 UIView *newView = UIView.new; 122 UIView *newView = UIView.new;
122 [superview addSubview:newView]; 123 [superview addSubview:newView];
@@ -126,8 +127,9 @@ it(@"should remove completed on commit", ^{ @@ -126,8 +127,9 @@ it(@"should remove completed on commit", ^{
126 127
127 [composite commit]; 128 [composite commit];
128 129
129 - [verify(delegate) addConstraint:(id)composite.childConstraints[0]];  
130 - [verify(delegate) addConstraint:(id)composite.childConstraints[1]]; 130 + expect(composite.childConstraints).to.haveCountOf(2);
  131 + expect(delegate.constraints).to.contain(composite.childConstraints[0]);
  132 + expect(delegate.constraints).to.contain(composite.childConstraints[1]);
131 }); 133 });
132 134
133 SpecEnd 135 SpecEnd
  1 +//
  2 +// MASConstraintDelegate.h
  3 +// Masonry
  4 +//
  5 +// Created by Jonas Budelmann on 28/07/13.
  6 +// Copyright (c) 2013 Jonas Budelmann. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +#import "MASConstraint.h"
  11 +
  12 +@interface MASConstraintDelegateMock : NSObject <MASConstraintDelegate>
  13 +
  14 +@property (nonatomic, strong) NSMutableArray *constraints;
  15 +
  16 +@end
  1 +//
  2 +// MASConstraintDelegate.m
  3 +// Masonry
  4 +//
  5 +// Created by Jonas Budelmann on 28/07/13.
  6 +// Copyright (c) 2013 Jonas Budelmann. All rights reserved.
  7 +//
  8 +
  9 +#import "MASConstraintDelegateMock.h"
  10 +
  11 +@implementation MASConstraintDelegateMock
  12 +
  13 +- (id)init {
  14 + self = [super init];
  15 + if (!self) return nil;
  16 +
  17 + self.constraints = NSMutableArray.new;
  18 +
  19 + return self;
  20 +}
  21 +
  22 +- (void)addConstraint:(id<MASConstraint>)constraint {
  23 + [self.constraints addObject:constraint];
  24 +}
  25 +
  26 +@end
@@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
9 #import "MASViewConstraint.h" 9 #import "MASViewConstraint.h"
10 #import "MASConstraint.h" 10 #import "MASConstraint.h"
11 #import "UIView+MASAdditions.h" 11 #import "UIView+MASAdditions.h"
  12 +#import "MASConstraintDelegateMock.h"
12 13
13 @interface MASViewConstraint () 14 @interface MASViewConstraint ()
14 15
@@ -23,7 +24,7 @@ @@ -23,7 +24,7 @@
23 24
24 SpecBegin(MASViewConstraint) 25 SpecBegin(MASViewConstraint)
25 26
26 -__block id<MASConstraintDelegate> delegate; 27 +__block MASConstraintDelegateMock *delegate;
27 __block UIView *superview; 28 __block UIView *superview;
28 __block MASViewConstraint *constraint; 29 __block MASViewConstraint *constraint;
29 __block UIView *otherView; 30 __block UIView *otherView;
@@ -31,7 +32,7 @@ __block UIView *otherView; @@ -31,7 +32,7 @@ __block UIView *otherView;
31 32
32 beforeEach(^{ 33 beforeEach(^{
33 superview = UIView.new; 34 superview = UIView.new;
34 - delegate = mockProtocol(@protocol(MASConstraintDelegate)); 35 + delegate = MASConstraintDelegateMock.new;
35 36
36 UIView *view = UIView.new; 37 UIView *view = UIView.new;
37 constraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:view.mas_width]; 38 constraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:view.mas_width];
@@ -47,9 +48,9 @@ describe(@"create equality constraint", ^{ @@ -47,9 +48,9 @@ describe(@"create equality constraint", ^{
47 48
48 it(@"should create equal constraint", ^{ 49 it(@"should create equal constraint", ^{
49 MASViewAttribute *secondViewAttribute = otherView.mas_top; 50 MASViewAttribute *secondViewAttribute = otherView.mas_top;
50 - MASViewConstraint *newConstraint = constraint.equalTo(secondViewAttribute); 51 + MASViewConstraint *newConstraint = (id)constraint.equalTo(secondViewAttribute);
51 52
52 - [verify(constraint.delegate) addConstraint:(id)constraint]; 53 + expect(delegate.constraints).to.contain(constraint);
53 expect(newConstraint).to.beIdenticalTo(constraint); 54 expect(newConstraint).to.beIdenticalTo(constraint);
54 expect(constraint.secondViewAttribute).to.beIdenticalTo(secondViewAttribute); 55 expect(constraint.secondViewAttribute).to.beIdenticalTo(secondViewAttribute);
55 expect(constraint.layoutRelation).to.equal(NSLayoutRelationEqual); 56 expect(constraint.layoutRelation).to.equal(NSLayoutRelationEqual);
@@ -57,9 +58,9 @@ describe(@"create equality constraint", ^{ @@ -57,9 +58,9 @@ describe(@"create equality constraint", ^{
57 58
58 it(@"should create greaterThanOrEqual constraint", ^{ 59 it(@"should create greaterThanOrEqual constraint", ^{
59 MASViewAttribute *secondViewAttribute = otherView.mas_top; 60 MASViewAttribute *secondViewAttribute = otherView.mas_top;
60 - MASViewConstraint *newConstraint = constraint.greaterThanOrEqualTo(secondViewAttribute);  
61 -  
62 - [verify(constraint.delegate) addConstraint:(id)constraint]; 61 + MASViewConstraint *newConstraint = (id)constraint.greaterThanOrEqualTo(secondViewAttribute);
  62 +
  63 + expect(delegate.constraints).to.contain(constraint);
63 expect(newConstraint).to.beIdenticalTo(constraint); 64 expect(newConstraint).to.beIdenticalTo(constraint);
64 expect(constraint.secondViewAttribute).to.beIdenticalTo(secondViewAttribute); 65 expect(constraint.secondViewAttribute).to.beIdenticalTo(secondViewAttribute);
65 expect(constraint.layoutRelation).to.equal(NSLayoutRelationGreaterThanOrEqual); 66 expect(constraint.layoutRelation).to.equal(NSLayoutRelationGreaterThanOrEqual);
@@ -67,9 +68,9 @@ describe(@"create equality constraint", ^{ @@ -67,9 +68,9 @@ describe(@"create equality constraint", ^{
67 68
68 it(@"create lessThanOrEqual constraint", ^{ 69 it(@"create lessThanOrEqual constraint", ^{
69 MASViewAttribute *secondViewAttribute = otherView.mas_top; 70 MASViewAttribute *secondViewAttribute = otherView.mas_top;
70 - MASViewConstraint *newConstraint = constraint.lessThanOrEqualTo(secondViewAttribute);  
71 -  
72 - [verify(constraint.delegate) addConstraint:(id)constraint]; 71 + MASViewConstraint *newConstraint = (id)constraint.lessThanOrEqualTo(secondViewAttribute);
  72 +
  73 + expect(delegate.constraints).to.contain(constraint);
73 expect(newConstraint).to.beIdenticalTo(constraint); 74 expect(newConstraint).to.beIdenticalTo(constraint);
74 expect(constraint.secondViewAttribute).to.beIdenticalTo(secondViewAttribute); 75 expect(constraint.secondViewAttribute).to.beIdenticalTo(secondViewAttribute);
75 expect(constraint.layoutRelation).to.equal(NSLayoutRelationLessThanOrEqual); 76 expect(constraint.layoutRelation).to.equal(NSLayoutRelationLessThanOrEqual);
@@ -110,8 +111,34 @@ describe(@"create equality constraint", ^{ @@ -110,8 +111,34 @@ describe(@"create equality constraint", ^{
110 expect(constraint.firstViewAttribute.layoutAttribute).to.equal(constraint.secondViewAttribute.layoutAttribute); 111 expect(constraint.firstViewAttribute.layoutAttribute).to.equal(constraint.secondViewAttribute.layoutAttribute);
111 }); 112 });
112 113
113 - xit(@"should create composite when passed array of views", ^{ 114 + it(@"should create composite when passed array of views", ^{
  115 + NSArray *views = @[UIView.new, UIView.new, UIView.new];
  116 + constraint.equalTo(views).priorityMedium().offset(-10);
  117 +
  118 + expect(delegate.constraints).to.haveCountOf(3);
  119 + for (MASViewConstraint *constraint in delegate.constraints) {
  120 + int index = [delegate.constraints indexOfObject:constraint];
  121 + expect(constraint.secondViewAttribute.view).to.beIdenticalTo(views[index]);
  122 + expect(constraint.firstViewAttribute.layoutAttribute).to.equal(NSLayoutAttributeWidth);
  123 + expect(constraint.secondViewAttribute.layoutAttribute).to.equal(NSLayoutAttributeWidth);
  124 + expect(constraint.layoutPriority).to.equal(MASLayoutPriorityDefaultMedium);
  125 + expect(constraint.layoutConstant).to.equal(-10);
  126 + }
  127 + });
114 128
  129 + it(@"should create composite when passed array of attributes", ^{
  130 + NSArray *viewAttributes = @[UIView.new.mas_height, UIView.new.mas_left];
  131 + constraint.equalTo(viewAttributes).priority(60).offset(10);
  132 +
  133 + expect(delegate.constraints).to.haveCountOf(2);
  134 + for (MASViewConstraint *constraint in delegate.constraints) {
  135 + int index = [delegate.constraints indexOfObject:constraint];
  136 + expect(constraint.secondViewAttribute.view).to.beIdenticalTo([viewAttributes[index] view]);
  137 + expect(constraint.firstViewAttribute.layoutAttribute).to.equal(NSLayoutAttributeWidth);
  138 + expect(constraint.secondViewAttribute.layoutAttribute).to.equal([viewAttributes[index] layoutAttribute]);
  139 + expect(constraint.layoutPriority).to.equal(60);
  140 + expect(constraint.layoutConstant).to.equal(10);
  141 + }
115 }); 142 });
116 }); 143 });
117 144
@@ -9,7 +9,4 @@ @@ -9,7 +9,4 @@
9 9
10 #define EXP_SHORTHAND 10 #define EXP_SHORTHAND
11 #import "Expecta.h" 11 #import "Expecta.h"
12 -  
13 - #define MOCKITO_SHORTHAND  
14 - #import <OCMockito/OCMockito.h>  
15 #endif 12 #endif
@@ -3,5 +3,4 @@ platform :ios, '6.0' @@ -3,5 +3,4 @@ platform :ios, '6.0'
3 target 'MasonryTests', :exclusive => true do 3 target 'MasonryTests', :exclusive => true do
4 pod 'Specta' 4 pod 'Specta'
5 pod 'Expecta' 5 pod 'Expecta'
6 - pod 'OCMockito'  
7 end 6 end
@@ -126,6 +126,15 @@ make.width.greaterThanOrEqualTo(@200); @@ -126,6 +126,15 @@ make.width.greaterThanOrEqualTo(@200);
126 make.width.lessThanOrEqualTo(@400) 126 make.width.lessThanOrEqualTo(@400)
127 ``` 127 ```
128 128
  129 +#### 4. NSArray
  130 +
  131 +An array of a mixture of any of the previous types
  132 +```obj-c
  133 +make.height.equalTo(@[view1.mas_height, view2.mas_height]);
  134 +make.height.equalTo(@[view1, view2]);
  135 +make.left.equalTo(@[view1, @100, view3.right]);
  136 +````
  137 +
129 ## Learn to prioritize 138 ## Learn to prioritize
130 139
131 > `.prority` allows you to specify an exact priority 140 > `.prority` allows you to specify an exact priority