2017-01-07 4 views
1

В @IBDesignable,@IBDesignable, NSLayoutConstraint для пропорциональной ширины множителя супервизора?

Я пытаюсь программно установить «ширина 20% от родителей»:

@IBDesignable 
class TwentyPercentExample:UIView { 

    func setup() { 
     let cWidth = NSLayoutConstraint(
      item: self, 
      attribute: NSLayoutAttribute.width, 
      relatedBy: NSLayoutRelation.equal, 
      toItem: self.superview, 
      attribute: NSLayoutAttribute.width, 
      multiplier: 0.2, 
      constant:0 
     ) 
     addConstraint(cWidth) 
     print("I seemed to added the width constraint....") 
     updateConstraintsIfNeeded() // could be useful.. 
    } 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     self.setup() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     self.setup() 
    } 

} 

(Таким образом, вы бы добавить UIView в раскадровке, возможно, установить его на якорь слева до супервизора, а затем смените класс на TwentyPercentExample.)

Странно это не работает. если вы это сделаете:

multiplier: 1, 
constant:100 

это красиво устанавливает его в режиме реального времени в раскадровке до 100 ширины. Замените на

multiplier: 1, 
constant:200 

и он отлично работает, меняет его в режиме реального времени на 200 ширины. Однако это просто не похоже на работу:

multiplier: 0.2, 
constant:0 

У меня есть toItem: неправильно, или что-то? В чем дело?

+0

Всякий раз, когда вы предоставляете ограничения программным образом, вам необходимо активировать ограничения. И ты этого не делал. Проверьте этот документ яблока https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/ProgrammaticallyCreatingConstraints.html. –

+1

@the_dahiya_boy Это неправда. Установка 'isActive' - это новый и лучший способ сделать это, но любой из них должен работать. В документах есть заметка «Свойство isActive автоматически добавляет и удаляет ограничение из правильного представления» –

+1

Это устаревшее использование автоматического макета. Замените весь метод этой единственной строкой: 'self.widthAnchor.constraint (equalTo: supiew! .widthAnchor, множитель: 0.2) .isActive = true'. Это также было бы ошибкой, так как у вас нет набора Superview. –

ответ

2

Я подозреваю, что проблема в том, что вы делаете это в init, когда self.superview является nil. Вы должны подождать, чтобы добавить ограничение до тех пор, пока оно не будет добавлено в супервизор. Возможно, в didMoveToSuperview(), хотя это может стать беспорядочным, поскольку вам нужно будет учитывать тот факт, что его можно было добавить в супервизор более одного раза.

Возможно, причина, по которой фиксированный постоянный случай работает, заключается в том, что его законный иметь ограничение, жестко закодированное до 100, с пунктом nil в качестве аргумента toItem:.


Таким образом, любой из этих

override func didMoveToSuperview() { setup() } 
... or ... 
override func layoutSubviews() { setup() } 

func setup() { 
    self.widthAnchor 
     .constraint(equalTo: superview!.widthAnchor, multiplier: 0.2) 
     .isActive = true 
} 

похоже на работу: но, кажется, работает неправильно и генерировать «агент разбился» ошибки в Xcode.

+0

Ты совершенно прав Джон - в IBDesignable, супервизор еще не установлен на этом этапе. – Fattie

+0

Ahh - 'layoutSubviews' - ​​это решение. – Fattie

+0

Это правда, что 'didMoveToSuperview()' также работает. Я не знаю, что предпочтительнее. Джон, кажется, «волшебный» «проблема, добавленная несколько раз» (что вызывает беспокойство). – Fattie

Смежные вопросы