neo
neo

Reputation: 1404

Why constraints are updated on scrolling of UITableView?

I have 2 simple UILabel that needs to be placed horizontally. One of them on right side of view, while second one is on the left side and gets all possible space. Here is my constraints:

    amountOfQuestions.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
    amountOfQuestions.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true


    topicName.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
    topicName.topAnchor.constraint(equalTo: topAnchor, constant: 8).isActive = true
    topicName.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8).isActive = true
    topicName.rightAnchor.constraint(equalTo: amountOfQuestions.leftAnchor, constant: -8).isActive = true

Seems like everything is ok, but when table view is shown, it looks like this:

enter image description here

But after I scroll couple of times my table up and down, it became normal:

enter image description here

Why my table is not shown immediately like in second picture?

Solution:

amountOfQuestions.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
    amountOfQuestions.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
    amountOfQuestions.setContentHuggingPriority(.required, for: .horizontal)
    amountOfQuestions.setContentCompressionResistancePriority(.required, for: .horizontal)

    topicName.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
    topicName.topAnchor.constraint(equalTo: topAnchor, constant: 8).isActive = true
    topicName.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8).isActive = true
    topicName.rightAnchor.constraint(equalTo: amountOfQuestions.leftAnchor, constant: -8).isActive = true
    topicName.setContentHuggingPriority(.required, for: .horizontal)
    topicName.setContentCompressionResistancePriority(.required, for: .vertical)


    let myBottom = topicName.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8)
    myBottom.priority = UILayoutPriority(rawValue: UILayoutPriority.required.rawValue - 1)
    myBottom.isActive = true

Upvotes: 0

Views: 518

Answers (2)

Sulthan
Sulthan

Reputation: 130122

There are multiple problems that can affect the layout and make it incorrectly defined:

  1. Never constrain content to the cell itself. Always constrain to the contentView of the cell, e.g.:

    amountOfQuestions.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -8).isActive = true
    

(make sure you are adding the labels as subviews of the contentView, not of the cell itself).

  1. If you want the size of the labels to have any effect, you need to set hugging and compression resistance priorities correctly. Otherwise the layout does not have to respect the content:

    // you want topic name to resize vertically to respect the content
    topicName.setHuggingPriority(.required, for: .vertical)
    topicName.setContentCompressionResistancePriority(.required, for: .vertical)
    
    // you want amount of question to resize horizontally to respect the content
    amountOfQuestions.setHuggingPriority(.required, for: .horizontal)
    amountOfQuestions.setContentCompressionResistancePriority(.required, for: .horizontal)
    

  1. To avoid layout conflicts during the first layout, it's a good idea to give one the of the vertical constraints a slightly lower layout priority:

    let bottomAnchor = topicName.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8)
    bottomAnchor.priority = UILayoutPriority(rawValue: UILayoutPriority.required.rawValue - 1)
    bottomAnchor.isActive = true
    

Upvotes: 2

Shehata Gamal
Shehata Gamal

Reputation: 100533

1- UILabels have an intrinsic content value , that means you don't have to specify a width / height for them , so when you place them horizontally like this

| - lbl1 - lbl2 - |

This causes a constraint ambiguity because autolayout need to know which label to trim when a one content is too bigger that's why you need to set horizontal compression resistance && setHuggingPriority to lbl2 = 1000

2- You need to lower priority of bottom constraint as the cell assumes a fixed height in the begining of layout and that height may conflict with current total height of the vertical content , so you lower it to avoid this conflict

Upvotes: 1

Related Questions