Search code examples
iosswiftiphoneautolayout

iOS | Layout constraint error when adding two views programatically


I have a piece of code to display image view and UILabel side by side.It displays as expected based on the constraints provided but there a lot of warnings in the console

Here is the error

[LayoutConstraints] Unable to simultaneously satisfy constraints.
    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:0x6000003d0190 V:|-(0)-[UIImageView:0x7faa7401b940]   (active, names: '|':Movies_TODO.MovieViewCell:0x7faa7402caa0'custom' )>",
    "<NSLayoutConstraint:0x6000003d05a0 UIImageView:0x7faa7401b940.bottom == Movies_TODO.MovieViewCell:0x7faa7402caa0'custom'.bottom   (active)>",
    "<NSLayoutConstraint:0x6000003d0640 UIImageView:0x7faa7401b940.height == 100   (active)>",
    "<NSLayoutConstraint:0x6000003e7070 'UIView-Encapsulated-Layout-Height' Movies_TODO.MovieViewCell:0x7faa7402caa0'custom'.height == 100.5   (active)>"
)

Will attempt to recover by breaking constraint

Here is my piece of my code

self.addSubview(movieImageView)
self.addSubview(titleLabel)

movieImageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
movieImageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
movieImageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
movieImageView.widthAnchor.constraint(equalToConstant: 100).isActive = true

movieImageView.heightAnchor.constraint(equalToConstant: 100).isActive = true

titleLabel.leadingAnchor.constraint(equalTo: movieImageView.trailingAnchor, constant: 20).isActive = true
titleLabel.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
titleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
titleLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

Solution

  • Your movieImageView has a constraint like height equal to 100 AND height equal to super view's height (this come from since you added top and bottom anchor constraints).


    1 - If you want to set movieImageView from top to bottom just delete movieImageView.heightAnchor.constraint(equalToConstant: 100).isActive = true.


    2 - If you want to set movieImageView's height constantly 100 just delete the line you don't want to set for the movieImageView ->

    // if you want to stick your imageView to bottom delete this
    movieImageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
    
    // if you want to stick your imageView to top delete this
    movieImageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
    

    With UIStackView

    • If you want to create a TableViewCell has left sided image and right sided label, you can use StackView and you can do what you want without any constraints.

    Create a UIStackView

    let stackView = UIStackView()
    

    Add your movieImageView and titleLabel

    stackView.addArrangedSubviews(movieImageView, titleLabel)
    stackView.axis = .horizontal
    stackView.spacing = 20.0
    

    Add your stackView to super.view

    self.addSubview(stackView)
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    stackView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
    stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
    
    stackView. trailingAnchor.constraint(equalTo: self. trailingAnchor).isActive = true
    stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
    

    If you want to set movieImageView's width from it's image, you should set Content Hugging Priority of the movieImageView

    movieImageView.setContentHuggingPriority(.defaultHigh, for: .horizontal)
    

    If you want to set titleLabel's width from it's text and resistant than the imageView, you should set Compression Resistance Priority of the titleLabel

    titleLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
    

    BONUS

    Intrinsic Content Size

    UIStackView Guide

    UIStackView Example of Hackingwithswift