Константа NSLayoutConstraint не обновляется после установки

У меня есть подкласс UIView с соответствующим файлом xib. В моем xib у меня есть свойство NSLayoutConstraint, которое я пытаюсь анимировать. У меня есть метод animateIn. Проблема в том, что работает только метод animateIn. Когда я снова пытаюсь обновить константу, она просто остается на прежнем значении.

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *horizontalConstraint;

Я пытаюсь обновить константу после нажатия кнопки. Но константа, похоже, не обновляется после установки. Он по-прежнему регистрирует 0 даже после установки его на -500. Я звоню layoutIfNeeded, но ничего не происходит.

// this works
- (void) animateIn { 
    [UIView animateWithDuration:1.0 delay:2.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        self.alpha = 1.0;
    } completion:^(BOOL finished) {

        [UIView animateWithDuration:1.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            self.horizontalConstraint.constant = 0;
            [self layoutIfNeeded];
        } completion:^(BOOL finished) {
        }];
    }];
}

// this does not work
- (IBAction)resume:(id)sender {
        self.horizontalConstraint.constant = -500;
        [self layoutIfNeeded];

        NSLog(@"%f",self.horizontalConstraint.constant); // this always stays 0
    }

ОБНОВЛЕНИЕ

Похоже, что мой NSLayoutConstraint равен (null), когда я хочу использовать его во второй раз. Это объясняет, почему он не обновляется. Как сохранить ссылку на него?


person Ramin Afshar    schedule 11.08.2014    source источник
comment
Если он стал null, попробуйте с указателем strong.   -  person Yogesh Suthar    schedule 11.08.2014


Ответы (5)


Вам нужно будет вызвать метод setNeedsUpdateConstraints соответствующего UIView(control) из которых присутствует ваш NSLayoutConstraint для обновления ограничения.

Например, UIButton

self.buttonConstraint.constant = 55;
[self.btnTest setNeedsUpdateConstraints];

В твоем случае

[self setNeedsUpdateConstraints];
person Yogesh Suthar    schedule 11.08.2014
comment
Это неправильно. Вы должны вызывать setNeedsUpdateConstraints, когда вам нужно их обновить, а затем изменять constant внутри метода updateViewConstraints, который вызывается автоматически. Или вы можете изменить константу в методе, который требует этого (чтобы код был более тесно связан), а затем вызвать setNeedsLayout в представлении ограничения superview. - person Iulian Onofrei; 29.03.2017
comment
Я не согласен с вашей характеристикой здесь. Вы можете переопределить updateConstraints(), чтобы облегчить сложный набор пакетных изменений. Но из документации: › Это почти всегда чище и проще для обновления ограничения сразу после того, как произошло затрагивающее изменение. ... › Вы должны переопределять этот метод только в том случае, если изменение ограничений происходит слишком медленно или когда представление производит ряд избыточных изменений. - person Stan; 29.04.2017

Я столкнулся с проблемой, когда в первый раз, когда я устанавливаю константу ограничения в коде, константа будет установлена, но затем после вызова layoutIfNeeded(), например:

myConstraint.constant = newValue;
[view layoutIfNeeded]

константа вернется к исходному значению! Я мог наблюдать за изменением значения в отладчике.

В конце концов я понял, что это произошло потому, что в раскадровке я задал вариацию константы. Например:

введите описание изображения здесь

Как только я удалил вариант, значение константы ограничения не изменилось обратно к исходному значению с вызовом layoutIfNeeded.

person CLK    schedule 12.04.2018
comment
Благодарю вас! Вы спасли мой день! - person alc77; 18.05.2018
comment
Это было и для меня тоже. Кто-нибудь понял, как правильно сделать оба? (Сохранение вариации, а также возможность программно изменить константу в коде где-то/как-то) - person xaphod; 24.04.2019
comment
@xaphod Я столкнулся с похожей проблемой. Я удалил вариант из xib и в итоге программно установил константу ограничения для класса размера во время изменения набора признаков. - person duncanc4; 21.06.2019
comment
Удивительно, решил мою проблему. Почти похоже на ошибку IB. - person Pranav Kasetti; 03.09.2019

Вы уверены, что это ограничение не деактивировано где-то? Установка для свойства active ограничения значения false приводит к тому, что иерархия представлений удаляет ограничение. Если у вас также нет ссылки на него, объект ограничения будет удален из памяти.

У меня была та же проблема, что и у вас, и я удалил «слабый», поэтому ограничение теперь является сильным свойством. Следовательно, при деактивации он не устанавливается в nil (поскольку мой контроллер представления всегда имеет сильный указатель на него), и я могу повторно активировать его и повторно установить его константу.

// NB: don't create these contraints outlets as "weak" if you intend to de-activate them, otherwise they would be set to nil when deactivated!
@IBOutlet private var captionViewHeightConstraint: NSLayoutConstraint!
person Frédéric Adda    schedule 15.04.2016

когда вы закончите изменения ограничений, просто позвоните:

[self setNeedsUpdateConstraints];
person Bogdan Somlea    schedule 11.08.2014

Свойство horizontalConstraint должно удерживаться самим представлением. Пока представление живо, свойство не должно быть нулевым (если только вы явно не установили его равным нулю где-то еще в коде). Дважды проверьте, не установили ли вы его на ноль по ошибке.

person Nikolay Markov    schedule 11.08.2014