Xcode: получить конкретное ограничение программно

Я программно встроил дочерний VC (DrawerViewController) в мой mainVC (HomeController), и теперь мне нужна ссылка topAnchor.

Я знаю, что могу ссылаться на отдельные ограничения с помощью IBOutlets и называть их, но я хочу научиться создавать вещи программно без раскадровки. И теперь я изо всех сил пытаюсь правильно сослаться на topAnchor моего дочернего контейнера программно для дальнейшей работы с этим var.

В качестве НПА это прекрасно сработало бы так:

@IBOutlet private var containerViewTopConstraint: NSLayoutConstraint!

Поэтому мне нужно было бы программно сослаться на мой topAnchor и назвать его в containerViewTopConstraint. Код программно встраиваемого дочернего VC:

let drawerViewController = DrawerViewController()

func addDrawer() {
    addChild(drawerViewController)
    view.addSubview(drawerViewController.view)
    drawerViewController.didMove(toParent: self)
    addDrawerConstraints()
}

func addDrawerConstraints() {
    drawerViewController.view.translatesAutoresizingMaskIntoConstraints = false
    drawerViewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
    drawerViewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
    drawerViewController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
    drawerViewController.view.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height).isActive = true
}

override func viewDidLoad() {
    super.viewDidLoad()

    addDrawer()
}

person Edward Kunz    schedule 26.11.2019    source источник
comment
«Я знаю, что могу ссылаться на отдельные ограничения с помощью IBOutlets и называть их, но я хочу научиться создавать вещи программно без раскадровки. " Так же. Когда вы создаете ограничение, назовите его. Или просто сохранить ссылку.   -  person matt    schedule 27.11.2019
comment
Как я могу назвать это? Я думаю, что я просто борюсь с синтаксисом. Я действительно новичок в Swift   -  person Edward Kunz    schedule 27.11.2019


Ответы (2)


Вот как я это делаю. Это включает в себя две вещи. Во-первых, установите ограничения, которые будут всегда одинаковыми, установив isActive = true. Затем для одного (или нескольких) активируйте/деактивируйте по мере необходимости:

let drawer = UIView()
var drawerOut = [NSLayoutConstraint]()
var drawerIn = [NSLayoutConstraint]()

// place in viewDidLoad()

drawer.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
drawer.widthAnchor.constraint(equalToConstant: 526).isActive = true
drawer.heightAnchor.constraint(equalToConstant: 374).isActive = true

drawerIn.append(drawer.topAnchor.constraint(equalTo: view.bottomAnchor, constant: 526))
drawerOut.append(drawer.topAnchor.constraint(equalTo: safeAreaView.bottomAnchor, constant: -370))
NSLayoutConstraint.activate(drawerIn)

// functions to open/close drawer

func openDrawer() {
    NSLayoutConstraint.deactivate(drawerIn)
    NSLayoutConstraint.activate(drawerOut)
    UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() }
}

func closeDrawer() {
    NSLayoutConstraint.deactivate(drawerOut)
    NSLayoutConstraint.activate(drawerIn)
    UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() }
}

UIView.animate(withDuration:) добавляет ко всему красивую анимацию.

РЕДАКТИРОВАТЬ: Да, вы можете назвать ограничения и обновить их. Пример этого — изменение константы heightAnchor — см. этот ответ. Я понял, что этот вопрос касается как не использования IB для ограничений, так и изменения ограничения.

person dfd    schedule 27.11.2019

Ты говоришь:

В качестве НПА это прекрасно сработало бы так:

@IBOutlet private var containerViewTopConstraint: NSLayoutConstraint!

Поэтому мне нужно было бы программно сослаться на мой topAnchor и назвать его в containerViewTopConstraint.

Да, так просто сделай это. Где у вас есть:

drawerViewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true

Помещать:

containerViewTopConstraint = drawerViewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20)
containerViewTopConstraint.isActive = true
person matt    schedule 27.11.2019