Обновление Frame/Constraints для программно добавленного UIView при изменении ориентации

У меня есть UIView, который я программно добавляю со следующим кодом в viewDidLoad.

dropMenuView = YNDropDownMenu(frame: CGRect(x: 0.0, y: 0, width: UIScreen.main.bounds.width, height: 40.0), dropDownViews: [typeView, brandView, priceView], dropDownViewTitles:["Type", "Brand", "Price"])
self.view.addSubview(dropMenuView)

Приведенный выше код создает представление с правильной шириной для текущей ориентации, но если пользователь меняет ориентацию своего устройства, ширина представления не обновляется. Я попытался добавить новое ограничение в viewWillTransitionTo:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    let widthConstraint = NSLayoutConstraint(item: dropMenuView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)

    dropMenuView.addConstraints([widthConstraint])
    dropMenuView.layoutIfNeeded()
}

Я пробовал несколько мутаций в приведенном выше коде, пытаясь заставить его работать. Обычно я получаю сообщение об ошибке: «NSLayoutConstraint for >: Unknown layout attribute»

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


person Alex Ritter    schedule 05.06.2018    source источник
comment
Что вы пытаетесь сделать с этим ограничением? Установить ширину 100? Установить ширину view.width + 100?   -  person vacawama    schedule 05.06.2018


Ответы (1)


Добавление ограничений во время изменения ориентации не является хорошей идеей. Если бы вы это сделали, вам нужно было бы удалить ранее добавленные ограничения, чтобы избежать чрезмерного ограничения вашего представления.

Ограничение, которое вы пытаетесь создать, неверно. Вы используете .notAnAttrubute только тогда, когда передаете nil в качестве второго представления.

Вместо этого я предлагаю вам использовать якоря макета. Их легче писать и читать:

dropMenuView = YNDropDownMenu(frame: CGRect.zero, dropDownViews: [typeView, brandView, priceView], dropDownViewTitles:["Type", "Brand", "Price"])
self.view.addSubview(dropMenuView)

// you need to set this if you are adding your own constraints and once
// yet set it, the frame is ignored (which is why we just passed CGRect.zero
// when creating the view)
dropMenuView.translatesAutoresizingMaskIntoConstraints = false

// Create the constraints and activate them.  This will set `isActive = true`
// for all of the constraints.  iOS knows which views to add them to, so
// you don't have to worry about that detail  
NSLayoutConstraint.activate([
    dropMenuView.topAnchor.constraint(equalTo: view.topAnchor),
    dropMenuView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    dropMenuView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    dropMenuView.heightAnchor.constraint(equalToConstant: 40)
])
person vacawama    schedule 05.06.2018
comment
Превосходно. Мне не приходило в голову использовать якоря. Это намного проще. Спасибо! - person Alex Ritter; 05.06.2018