accept array in equality blocks
Showing
16 changed files
with
179 additions
and
75 deletions
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 |
MasonryTests/MASConstraintDelegateMock.h
0 → 100644
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 |
MasonryTests/MASConstraintDelegateMock.m
0 → 100644
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 |
@@ -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 |
-
Please register or login to post a comment