简体   繁体   中英

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

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

You have set the bottom anchor and top anchor of your movieImageView which indirectly saying the height of your movieImageView.

After setting the height already you again changing your height to some constant value 100.

To avoid this warning remove

movieImageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

This warning is because of redundant constraints for same property.

You try the bellow constraints

    movieImageView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
    movieImageView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).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.view.safeAreaLayoutGuide.topAnchor).isActive = true
    titleLabel.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
    titleLabel.bottomAnchor.constraint(equalTo: self.movieImageView.bottomAnchor).isActive = true

The result of this constraints is

约束的结果

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM