Как ограничения просмотра много раз в разных ситуациях программно в Swift? - PullRequest
0 голосов
/ 26 января 2019

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

у меня есть ограничения, все мои представления в представлении сначала загрузили метод ия должен снова ограничить свой tableView в слушателе меток.

вот мой код для первого ограничения

 override func setupViews() {
    super.setupViews()


    view.addSubview(header)
    view.addSubview(serachOptionView)
    view.addSubview(tableView)
    header.addSubview(mytitle)
    view.addSubview(serachBarView)

    serachBarView.addSubview(serachInCityLabel)
    serachBarView.addSubview(serachInCountryLabel)
    serachBarView.addSubview(serachInTransitLabel)
    serachBarView.addSubview(advanceSearch)
    serachBarView.addSubview(columnLabelLeft)
    serachBarView.addSubview(columnLabelRight)




    //TO - DO header

    header.translatesAutoresizingMaskIntoConstraints=false
    header.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive=true
    header.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive=true
    header.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive=true
    header.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.17).isActive=true
    header.backgroundColor =  UIColor.init(patternImage: UIImage(named: "test.png")!)





    // MARK -- serachBarView


    serachBarView.translatesAutoresizingMaskIntoConstraints=false
    serachBarView.trailingAnchor.constraint(equalTo: header.trailingAnchor, constant: -3).isActive=true
    serachBarView.leadingAnchor.constraint(equalTo: header.leadingAnchor, constant: 3).isActive=true
    serachBarView.bottomAnchor.constraint(equalTo: header.bottomAnchor, constant: -1).isActive=true
    serachBarView.heightAnchor.constraint(equalTo: header.heightAnchor, multiplier: 0.27).isActive=true



    // MARK -- INCity

    serachInCityLabel.translatesAutoresizingMaskIntoConstraints=false
    serachInCityLabel.trailingAnchor.constraint(equalTo: serachBarView.trailingAnchor, constant: -5).isActive=true
    serachInCityLabel.topAnchor.constraint(equalTo: serachBarView.topAnchor, constant: 1).isActive=true
    serachInCityLabel.bottomAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: -1).isActive=true
    serachInCityLabel.widthAnchor.constraint(equalTo: serachBarView.widthAnchor, multiplier: 0.23).isActive=true


    // MARK -- columnLabelRight

    columnLabelRight.translatesAutoresizingMaskIntoConstraints=false
    columnLabelRight.trailingAnchor.constraint(equalTo: serachInCityLabel.leadingAnchor, constant: 0).isActive=true
    columnLabelRight.topAnchor.constraint(equalTo: serachInCityLabel.topAnchor, constant: 4).isActive=true
    columnLabelRight.bottomAnchor.constraint(equalTo: serachInCityLabel.bottomAnchor, constant: -4).isActive=true
    columnLabelRight.widthAnchor.constraint(equalToConstant: 1.5).isActive=true



    // MARK -- INCountry

    serachInCountryLabel.translatesAutoresizingMaskIntoConstraints=false
    serachInCountryLabel.trailingAnchor.constraint(equalTo: columnLabelRight.leadingAnchor, constant: 0).isActive=true
    serachInCountryLabel.topAnchor.constraint(equalTo: serachBarView.topAnchor, constant: 1).isActive=true
    serachInCountryLabel.bottomAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: -1).isActive=true
    serachInCountryLabel.widthAnchor.constraint(equalTo: serachBarView.widthAnchor, multiplier: 0.24).isActive=true


    // MARK -- columnLabelRight

    columnLabelLeft.translatesAutoresizingMaskIntoConstraints=false
    columnLabelLeft.trailingAnchor.constraint(equalTo: serachInCountryLabel.leadingAnchor, constant: 0).isActive=true
    columnLabelLeft.topAnchor.constraint(equalTo: serachInCountryLabel.topAnchor, constant: 4).isActive=true
    columnLabelLeft.bottomAnchor.constraint(equalTo: serachInCountryLabel.bottomAnchor, constant: -4).isActive=true
    columnLabelLeft.widthAnchor.constraint(equalToConstant: 1.5).isActive=true

    // MARK -- INTranis


    serachInTransitLabel.translatesAutoresizingMaskIntoConstraints=false
    serachInTransitLabel.trailingAnchor.constraint(equalTo: serachInCountryLabel.leadingAnchor, constant: 0).isActive=true
    serachInTransitLabel.topAnchor.constraint(equalTo: serachBarView.topAnchor, constant: 1).isActive=true
    serachInTransitLabel.bottomAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: -1).isActive=true
    serachInTransitLabel.widthAnchor.constraint(equalTo: serachBarView.widthAnchor, multiplier: 0.24).isActive=true


    // MARK -- advance search


    advanceSearch.translatesAutoresizingMaskIntoConstraints=false
    advanceSearch.trailingAnchor.constraint(equalTo: serachInTransitLabel.leadingAnchor, constant: 0).isActive=true
    advanceSearch.topAnchor.constraint(equalTo: serachBarView.topAnchor, constant: 1).isActive=true
    advanceSearch.bottomAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: -1).isActive=true
    advanceSearch.widthAnchor.constraint(equalTo: serachBarView.widthAnchor, multiplier: 0.24).isActive=true


    // MARK -- tableView


    tableView.translatesAutoresizingMaskIntoConstraints=false
    tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive=true

    tableView.topAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: 0).isActive=true
    tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive=true
    tableView.delegate=self
    tableView.dataSource=self
    tableView.register(specialGoodCell.self, forCellReuseIdentifier: "myCell")


}

и переместиться ниже моей таблицы. View here:

@objc func labelAction(){

      // MARK -- tableView


        tableView.translatesAutoresizingMaskIntoConstraints=false
        tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive=true

        tableView.topAnchor.constraint(equalTo: mypopUpView.bottomAnchor, constant: 0).isActive=true
        tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive=true
        tableView.delegate=self
        tableView.dataSource=self
        tableView.register(specialGoodCell.self, forCellReuseIdentifier: "myCell")

}

ирезультат - отсутствие движения, и это предупреждение:

не может одновременно удовлетворить ограничения.

    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x28276f750 UIView:0x13fd45270.bottom == UIView:0x13fd4b2f0.bottom - 1   (active)>",
    "<NSLayoutConstraint:0x28276f610 V:[UIView:0x13fd45270]-(0)-[UITableView:0x1400a0000]   (active)>",
    "<NSLayoutConstraint:0x28276f2a0 V:[UIView:0x13fd4b2f0]-(40)-[UIView:0x13fd18a40]   (active)>",
    "<NSLayoutConstraint:0x28276f8e0 UIView:0x13fd18a40.height == 0.16*UIView:0x13fe428e0.height   (active)>",
    "<NSLayoutConstraint:0x28276a990 V:[UIView:0x13fd18a40]-(0)-[UITableView:0x1400a0000]   (active)>",
    "<NSLayoutConstraint:0x28276cb40 'UIView-Encapsulated-Layout-Height' UIView:0x13fe428e0.height == 568   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x28276f2a0 V:[UIView:0x13fd4b2f0]-(40)-[UIView:0x13fd18a40]   (active)>

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Системе не нравятся множественные ограничения, назначенные привязке с одинаковым приоритетом, потому что они конфликтуют, и система «ломает» одно из них, чтобы удовлетворить хотя бы одно.Приоритет по умолчанию для ограничений, если не указано иное, составляет required (1000).Вы можете назначить несколько ограничений для привязки и активировать желаемое, назначая им различные приоритеты, такие как defaultLow и defaultHigh, и переключайте их от своего имени.

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

class MyViewController: UIViewController {

    // ...

    // Keep a reference to the constraints you want to change
    // depending on user interaction or desired state 
    // in your view controller class

    var tableViewConstraintTopAnchor1: NSLayoutConstraint!
    var tableViewConstraintTopAnchor2: NSLayoutConstraint!

    // ...

}

Затем в функции setupViews назначьте их:

func setupViews() {

    // ...

    // adding subviews and other constraints

    // ...

    // MARK -- tableView


    tableView.translatesAutoresizingMaskIntoConstraints=false
    tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive=true
    tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive=true

    // assign (desired, but conflicting) constraints with different priority

    tableViewConstraintTopAnchor1 = tableView.topAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: 0)
    tableViewConstraintTopAnchor1.priority = .defaultHigh
    tableViewConstraintTopAnchor1.isActive = true

    tableViewConstraintTopAnchor2 = tableView.topAnchor.constraint(equalTo: mypopUpView.bottomAnchor, constant: 0)
    tableViewConstraintTopAnchor2.priority = .defaultLow
    tableViewConstraintTopAnchor2.isActive = true

    tableView.delegate = self
    tableView.dataSource = self
    tableView.register(specialGoodCell.self, forCellReuseIdentifier: "myCell")

}

В своей функции labelAction вы просто переключаете приоритет ограниченийи попросите систему обновить макет вашего представления.

@objc func labelAction(){

    // MARK -- tableView

    // Switch the priority of the desired constraint to defaultHigh
    // the other ones to defaultLow

    tableViewConstraintTopAnchor1.priority = .defaultLow
    tableViewConstraintTopAnchor2.priority = .defaultHigh

    view.setNeedsLayout()
    view.layoutIfNeeded()

}

Можно также поместить это в анимационный блок UIView и анимировать все это:

@objc func labelAction(){

    // MARK -- tableView

    UIView.animate(withDuration: 0.2) {

         self.tableViewConstraintTopAnchor1.priority = .defaultLow
         self.tableViewConstraintTopAnchor2.priority = .defaultHigh

         self.view.setNeedsLayout()
         self.view.layoutIfNeeded()

    }

}

Назначениеоба ограничения для вашего tableView в viewDidLoad() (или функции, которую вы вызываете в нем) работают только в том случае, если mypopUpView уже существует и находится в той же иерархии отображения - пока не видел его в вашем коде;)

0 голосов
/ 28 января 2019

например ... в сделанных мьютипл ограничениях у вас есть ведущий, трейлинг, а затем и ширина. Вы не можете иметь начальное слово 5, затем конечный -5, но также указать ширину, потому что вы уже указали ширину с ограничениями в начале и в конце, если это имеет смысл? если не расскажешь и плохо объясню более подробно. в основном, если ваш экран был шириной 300 пикселей. у вас есть метка, и вы ограничиваете ее началом 50, трейлингом -50 ... тогда ширина вашей метки автоматически составит 200 ... вы не можете добавить привязку ширины чего-либо, потому что она не сможет удовлетворить все ваши ограничения.

...