NSLayoutConstraints are awesome. But like many cocoa technologies (strangely, all the ones that I like) the learning curve is fairly steep.
The goals was simple, I wanted to make a Numeric pin pad that would center itself in it's container view, while ensuring that all the buttons remained square, and aligned .... Ok, maybe not so simple.
Lastly, if your wondering why i've adopted this strange grouping mechanism inside my loop, I wanted the subview index have a 1-1 mapping with the button number, with out having to resort to setting tags. This way in the button handers I can look up the index of the sender in the subview collection, and know which button it is.
Like 99% of cocoa code, it's not concise. Disfrutarlo!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- (void)updateConstraints { | |
NSMutableArray *constraints = [NSMutableArray array]; | |
NSDictionary *views; | |
NSDictionary *metrics = @{}; | |
void (^squareConstraint)(UIView *) = ^(UIView *aView) { | |
[constraints addObject:[NSLayoutConstraint constraintWithItem:aView | |
attribute:NSLayoutAttributeHeight | |
relatedBy:NSLayoutRelationEqual | |
toItem:aView | |
attribute:NSLayoutAttributeWidth | |
multiplier:1.0 | |
constant:0]]; | |
}; | |
//Iterate in threes | |
for (NSUInteger idx=0; idx < self.subviews.count; idx++) { | |
if (idx % 3 == 0 && idx >= 1 && idx <= 9) { | |
views = @{ | |
@"upperLeft": (idx > 3) ? self.subviews[idx-3] : [NSNull null], //Get the left most view on the upper row | |
@"left":self.subviews[idx-2], | |
@"center":self.subviews[idx-1], | |
@"right":self.subviews[idx] | |
}; | |
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=1)-[left]-[center(==left)]-[right(==left)]-(>=1)-|" | |
options:NSLayoutFormatAlignAllCenterY|NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom | |
metrics:metrics | |
views:views]]; | |
[constraints addObject:[NSLayoutConstraint constraintWithItem:views[@"center"] | |
attribute:NSLayoutAttributeCenterX | |
relatedBy:NSLayoutRelationEqual | |
toItem:self | |
attribute:NSLayoutAttributeCenterX | |
multiplier:1.0 | |
constant:0.0]]; | |
if (views[@"upperLeft"] == [NSNull null]) { | |
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[left]" | |
options:0 | |
metrics:metrics | |
views:views]]; | |
} else { | |
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[upperLeft]-[left]" | |
options:0 | |
metrics:metrics | |
views:views]]; | |
} | |
} | |
if (idx == self.subviews.count -1 ) { | |
//Place the '0' and delete button | |
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[zero]-[delete(==zero)]" | |
options:NSLayoutFormatAlignAllCenterY|NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom | |
metrics:metrics | |
views:@{ | |
@"zero":self.subviews.firstObject, | |
@"delete":self.subviews.lastObject | |
}]]; | |
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[upperCenter]-[zero(==upperCenter)]-|" | |
options:NSLayoutFormatAlignAllCenterX | |
metrics:metrics | |
views:@{ | |
@"zero":self.subviews.firstObject, | |
@"upperCenter":views[@"center"] | |
}]]; | |
} | |
//Make them all square | |
squareConstraint(self.subviews[idx]); | |
} | |
[self addConstraints:constraints]; | |
[super updateConstraints]; | |
} |