UIStoryboard, как программно заменить ограничения?

У меня есть контроллер представления, выложенный в раскадровке с включенным автомакетом, и я ищу способ изменить ограничения, чтобы мой вид мог поворачиваться в ландшафт и переставлять кнопки на экране. Когда я пробую приведенный ниже код, я получаю около двух десятков сообщений «невозможно удовлетворить ограничения, нарушая ограничение...», которые я не могу расшифровать.

Есть ли способ динамически заменить ограничения из раскадровки ограничениями, которые я указываю программно? Я хочу полностью переопределить расположение кнопок, которое я определил в раскадровке.

-(void)updateViewConstraints
{
    [super updateViewConstraints];

    self.loginButton.translatesAutoresizingMaskIntoConstraints = NO;
    self.getStartedButton.translatesAutoresizingMaskIntoConstraints = NO;
    self.takeTourButton.translatesAutoresizingMaskIntoConstraints = NO;



    [self.loginButton removeConstraints:self.loginButton.constraints];
    [self.getStartedButton removeConstraints:self.getStartedButton.constraints];
    [self.takeTourButton removeConstraints:self.takeTourButton.constraints];


    one = self.loginButton;
    two = self.getStartedButton;
    three = self.takeTourButton;


    NSDictionary *metrics = @{@"height":@50.0,@"width":@100.0,@"leftSpacing":@110.0};
    NSDictionary *views = NSDictionaryOfVariableBindings(one,two,three);

    [self.view removeConstraints:activeTestLabelConstraints];
    [activeTestLabelConstraints removeAllObjects];

    if(isRotatingToLandscape)
    {

        [self registerConstraintsWithVisualFormat:@"|-[one(two)]-[two(three)]-[three]-|" options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:metrics views:views];
        [self registerConstraintsWithVisualFormat:@"V:[one(height)]-|" options:0 metrics:metrics views:views];

    }else
    {

        [self registerConstraintsWithVisualFormat:@"|-leftSpacing-[one(width)]" options:0 metrics:metrics views:views];
        [self registerConstraintsWithVisualFormat:@"[two(width)]" options:0 metrics:metrics views:views];
        [self registerConstraintsWithVisualFormat:@"[three(width)]" options:0 metrics:metrics views:views];
        [self registerConstraintsWithVisualFormat:@"V:[one(height)]-[two(75)]-[three(100)]-|" options:NSLayoutFormatAlignAllCenterX metrics:metrics views:views];
    }


}

Обновлено ответом Роба, вот метод удаления ограничений, который я использую

-(void)removeConstraintForView:(UIView*)viewToModify
{

    UIView* temp = viewToModify;
    [temp removeFromSuperview];
    [self.view addSubview:temp];

}

person Alex Stone    schedule 25.07.2013    source источник


Ответы (1)


Похоже, вы хотите просто удалить все ограничения на представление. Поскольку ограничения на представление часто удерживаются предком представления, не очевидно, как легко удалить все ограничения. Но на самом деле это довольно легко.

Удаление представления из иерархии представлений удаляет любые ограничения между представлением и другими представлениями за его пределами. Поэтому просто удалите свой вид из его супервизора, а затем добавьте его обратно:

// Remove constraints betwixt someView and non-descendants of someView.
UIView *superview = someView.superview;
[someView removeFromSuperview];
[superview addSubview:someView];

Если между someView и его потомками существуют какие-либо ограничения, эти ограничения могут удерживаться самим someView (но не могут удерживаться потомками someView). Если вы хотите также удалить эти ограничения, вы можете сделать это напрямую:

// Remove any remaining constraints betwixt someView and its descendants.
[someView removeConstraints:[someView constraints]];
person rob mayoff    schedule 25.07.2013
comment
Я заметил, что удаление подпредставления из суперпредставления, похоже, не работает для ограничений, определенных для этого подпредставления (например, закрепленной высоты и ширины). - person Alex Stone; 29.07.2013
comment
Вторая часть моего ответа удалит ограничения по ширине и высоте. - person rob mayoff; 29.07.2013
comment
это сработало.. но моя проблема в том, что если в моем uiview есть кнопки в своих подвидах, кнопки больше не получают события касания, когда я отсоединяю, а затем снова присоединяю их родителя.. я не знаю, как обойти это - person abbood; 26.09.2013
comment
хорошо, просто чтобы никто не попал в ту же ловушку, что и я.. мне пришлось сделать несколько вещей, чтобы выяснить, в чем проблема (хотя некоторые из них не связаны с вышеуказанной проблемой.. я думал, что это все еще может помочь) 1. не смог используйте спасительное recursiveDescription в журнале моего компилятора. мой параметр оптимизации компилятора был включен 2. выяснил это, установив translatesAutoresizingMaskIntoConstraints = NO в представлении контейнера.. и не установка ширины/высоты ..› - person abbood; 26.09.2013
comment
‹.. layoutcontrain, представление контейнера всегда получалось с нулевой шириной/высотой.. ПЛОХАЯ ИДЕЯ! поэтому я просто установил ограничение ширины/высоты (например, NSString *visualFormatString1 = @V:[button(›=41)]-100-|; NSString *visualFormatString2 = @|-[button(›=290)]- |;) И ГОТОВО! - person abbood; 26.09.2013
comment
Предупреждение: любые ссылки на IBOutlets будут равны нулю после удаления и повторного добавления представлений. - person Graham Perks; 13.06.2014
comment
Почему они будут равны нулю? - person rob mayoff; 21.11.2014