Давайте предположим, что у меня есть этот UIView
:AutoLayout, ограничения и анимация
с этими относительными ограничениями:
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *leftMarginConstraint;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *topMarginConstraint;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *widthConstraint;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *heightConstraint;
Хорошо, теперь давайте предположим, что, когда пользователь нажимает на эту UIButton
в кнопка должна перейти в нижний правый угол представления. Мы можем легко использовать два ограничения, определяющие нижнее пространство между кнопкой и нижней маской руководства и правое пространство (конечное пространство) от кнопки и правого края представления.
Проблема заключается в том, что у UIButton
уже были два ограничения (слева/сверху) и два ограничения, определяющие его ширину и высоту, поэтому мы не можем добавить два новых ограничения, потому что они будут конфликтовать с другими.
Простая и распространенная ситуация для сценария анимации, но это вызывает у меня некоторые проблемы. Идеи?
EDIT
Когда пользователь нажимает на UIButton
, мне нужно, чтобы кнопка:
- изменить свое название на "вторую"
- ждать 1 секунду и перейти к снизу- правый угол (удалите ограничения верхнего и левого полей и добавьте ограничения нижнего и левого полей)
- изменить название на «Третий»
- подождать 1 секунду и перейти в верхнем правом углу (удаление нижнего поля ограничения и добавить верхнее поле ограничения)
ли я серьезно обязан использовать этот грязный код?
@implementation ViewController
{
NSLayoutConstraint *_topMarginConstraint;
NSLayoutConstraint *_leftMarginConstraint;
NSLayoutConstraint *_bottomMarginConstraint;
NSLayoutConstraint *_rightMarginConstraint;
}
- (IBAction)buttonPressed:(id)sender
{
UIButton *button = sender;
// 1.
[sender setTitle:@"Second" forState:UIControlStateNormal];
// 2.
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
[button removeConstraints:@[self.leftMarginConstraint, self.topMarginConstraint]];
_bottomMarginConstraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeBottom
relatedBy:0 toItem:button
attribute:NSLayoutAttributeBottom
multiplier:1
constant:20];
[self.view addConstraint:_bottomMarginConstraint];
_rightMarginConstraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeRight
relatedBy:0 toItem:button
attribute:NSLayoutAttributeRight
multiplier:1
constant:20];
[self.view addConstraint:_rightMarginConstraint];
[UIView animateWithDuration:1 animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
// 3.
[sender setTitle:@"Third" forState:UIControlStateNormal];
// 4.
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
[button removeConstraint:_bottomMarginConstraint];
_topMarginConstraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeTop
relatedBy:0 toItem:button
attribute:NSLayoutAttributeTop
multiplier:1
constant:20];
[UIView animateWithDuration:1 animations:^{
[self.view layoutIfNeeded];
}];
});
}];
});
}
Серьезный? : D
Есть ли в любом случае избежать раздражающего исключения 'UIViewAlertForUnsatisfiableConstraints:', которое происходит между удалением и добавлением конгруэнтных ограничений? – Glavid