Programmatically made constraints are not working

update constraints programmatically swift
ios update constraints programmatically
add constraints programmatically swift 4
ios add constraint to superview programmatically
add leading and trailing constraints programmatically swift
nslayoutconstraint programmatically objective c
change top constraint programmatically swift
swift remove constraint programmatically

As I want to move away from xib and make my layout programmatically, I found that using the same exact constraints doesn't work as I would expect.

I want to make this UITableViewCell It's a quite simple cell with a small icon to its right as well as an Activity Indicator so I can toggle which one I want to see. They are inside a View and to their left is a label

Those are my constraints in the outline view And it works perfectly. However when I'm removing the XIB and doing all of the code myself, nothing works anymore

So here's my code:

class StandardRow: UITableViewCell {    
    private var initialWidth: CGFloat = 20


public var fetching: Bool = false {
    didSet {
        if (fetching) {
            activityIndicator?.startAnimating()
        } else {
            activityIndicator?.stopAnimating()
        }

        changeImageWidth()
    }
}

public var rightImage: UIImage? = nil {
    didSet {
        rightImageView?.image = rightImage
        changeImageWidth()
    }
}

private func changeImageWidth() {
    if (activityIndicator?.isAnimating) ?? false || rightImage != nil {
        imageWidth?.constant = initialWidth
    } else {
        imageWidth?.constant = 0
    }
}

override func prepareForReuse() {
    valueLabel?.text = ""
    imageView?.image = nil
    rightImage = nil
    fetching = false
    textLabel?.text = ""
    accessoryType = .none
}


//Views
private var imageContainer = UIView()
private var rightImageView = UIImageView()
private var activityIndicator: UIActivityIndicatorView? = UIActivityIndicatorView()
public var valueLabel: UILabel? = UILabel()
private var imageWidth: NSLayoutConstraint? = nil

override init(style: UITableViewCell.CellStyle = .default, reuseIdentifier: String? = nil) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    buildView()
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
    buildView()
}

func buildView() {
    contentView.addSubview(valueLabel!)
    imageContainer.addSubview(rightImageView)
    imageContainer.addSubview(activityIndicator!)
    contentView.addSubview(imageContainer)

    imageContainer.backgroundColor = .red
}

override func layoutSubviews() {
    super.layoutSubviews()

    //IMAGE CONTAINER CONSTRAINTS
    imageWidth = NSLayoutConstraint(item: imageContainer, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: initialWidth)
    imageWidth?.priority = UILayoutPriority(rawValue: 999)
    imageWidth?.isActive = true
    let bottomImageContainerConstraint = NSLayoutConstraint(item: imageContainer, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottom, multiplier: 1, constant: 0)
    bottomImageContainerConstraint.isActive = true
    bottomImageContainerConstraint.priority = UILayoutPriority(rawValue: 999)

    let topImageContainerConstraint = NSLayoutConstraint(item: imageContainer, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .top, multiplier: 1, constant: 0)
    topImageContainerConstraint.isActive = true
    topImageContainerConstraint.priority = UILayoutPriority(rawValue: 999)

    let trailingImageContainerConstraint = NSLayoutConstraint(item: imageContainer, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: 5)
    trailingImageContainerConstraint.priority = UILayoutPriority(rawValue: 999)
    trailingImageContainerConstraint.isActive = true

    let centerYImageContainerConstraint = NSLayoutConstraint(item: imageContainer, attribute: .centerY, relatedBy: .equal, toItem: contentView, attribute: .centerY, multiplier: 1, constant: 0)
    centerYImageContainerConstraint.isActive = true
    centerYImageContainerConstraint.priority = UILayoutPriority(rawValue: 999)
    //VALUE LABEL CONSTRAINTS
    let trailingValueLabelConstraint = NSLayoutConstraint(item: valueLabel!, attribute: .trailing, relatedBy: .equal, toItem: imageContainer, attribute: .leading, multiplier: 1, constant: 5)
    trailingValueLabelConstraint.isActive = true
    trailingValueLabelConstraint.priority = UILayoutPriority(rawValue: 999)

    let centerYValueLabelConstraint = NSLayoutConstraint(item: valueLabel!, attribute: .centerY, relatedBy: .equal, toItem: contentView, attribute: .centerY, multiplier: 1, constant: 0)
    centerYValueLabelConstraint.isActive = true
    centerYValueLabelConstraint.priority = UILayoutPriority(rawValue: 999)
    //ACTIVITY INDICATOR CONSTRAINGS
    NSLayoutConstraint(item: activityIndicator!, attribute: .trailing, relatedBy: .equal, toItem: imageContainer, attribute: .trailing, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: activityIndicator!, attribute: .leading, relatedBy: .equal, toItem: imageContainer, attribute: .leading, multiplier: 1, constant: 11).isActive = false
    NSLayoutConstraint(item: activityIndicator!, attribute: .bottom, relatedBy: .equal, toItem: imageContainer, attribute: .bottom, multiplier: 1, constant: 11).isActive = false
    NSLayoutConstraint(item: activityIndicator!, attribute: .top, relatedBy: .equal, toItem: imageContainer, attribute: .top, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: activityIndicator!, attribute: .centerY, relatedBy: .equal, toItem: imageContainer, attribute: .centerY, multiplier: 1, constant: 0).isActive = true
    //RIGHT IMAGE VIEW CONSTRAINTS
    NSLayoutConstraint(item: rightImageView, attribute: .trailing, relatedBy: .equal, toItem: activityIndicator!, attribute: .trailing, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: rightImageView, attribute: .leading, relatedBy: .equal, toItem: rightImageView, attribute: .leading, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: rightImageView, attribute: .bottom, relatedBy: .equal, toItem: activityIndicator!, attribute: .bottom, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: rightImageView, attribute: .top, relatedBy: .equal, toItem: activityIndicator!, attribute: .top, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: rightImageView, attribute: .centerY, relatedBy: .equal, toItem: activityIndicator!, attribute: .centerY, multiplier: 1, constant: 0).isActive = true
    //changeImageWidth()
}}

So I have a few ideas to where it can come from, firstly being "translatesAutoresizingMaskIntoConstraints" set to true by default, but when I'm setting it to false in the superview then my cell doesn't show anymore and in the contentView, Xcode tells me I shouldn't do that because of an undefined behaviour

I'm also using Reveal to debug my UI and then I found those peculiar values:

Which is not what I want, Reveal is reporting that those constraints are translating the autoresizing mask of the view to autolayout so it would confirm the previous theory. I did set the priority to 999 to some of the constraints because otherwise they would be broken.

I'm actually at a dead end and I think I'm missing something but I can't pinpoint what as I don't have enough experience with non-interface builder constraints

Try Anchors, it's much easier.

Example

var redView = UIView()
redView.backgroundColor = .red
anyView.addsubView(redView)
redView.translatesAutoresizingMaskIntoConstraints = false
redView.centerXAnchor.constraint(equalTo: self.parentView.centerXAnchor).isActive = true
redView.centerYAnchor.constraint(equalTo: self.parentView.centerYAnchor).isActive = true
redView.heightAnchor.constraint(equalToConstant: 100).isActive = true
redView.widthAnchor.constraint(equalToConstant: 100).isActive = true

Auto Layout Guide: Programmatically Creating Constraints, of constraint directly in Interface Builder (see Working with Constraints in Interface Use these guides when programmatically creating constraints to the These rules are not enforced by the NSLayoutConstraint API. Therefore some constraints (for example, aspect ratios) cannot be created using the� For those times that you do have to create your constraints programmatically, you have three options to choose from: Layout Anchors - This API provides access to the anchor properties (such as TopAnchor, BottomAnchor or HeightAnchor) of the UI items being constrained.

You can add the same method to your UIView extension

 func constrainToEdges(_ subview: UIView, top: CGFloat = 0, bottom: CGFloat = 0, leading: CGFloat = 0, trailing: CGFloat = 0) {

    subview.translatesAutoresizingMaskIntoConstraints = false

    let topContraint = NSLayoutConstraint(
        item: subview,
        attribute: .top,
        relatedBy: .equal,
        toItem: self,
        attribute: .top,
        multiplier: 1.0,
        constant: top)

    let bottomConstraint = NSLayoutConstraint(
        item: subview,
        attribute: .bottom,
        relatedBy: .equal,
        toItem: self,
        attribute: .bottom,
        multiplier: 1.0,
        constant: bottom)

    let leadingContraint = NSLayoutConstraint(
        item: subview,
        attribute: .leading,
        relatedBy: .equal,
        toItem: self,
        attribute: .leading,
        multiplier: 1.0,
        constant: leading)

    let trailingContraint = NSLayoutConstraint(
        item: subview,
        attribute: .trailing,
        relatedBy: .equal,
        toItem: self,
        attribute: .trailing,
        multiplier: 1.0,
        constant: trailing)

    addConstraints([
        topContraint,
        bottomConstraint,
        leadingContraint,
        trailingContraint])
}

Auto Layout in Swift: Writing constraints programmatically, Auto Layout Constraints written programmatically in code by making use of The constraints will make sure that your views adjust to any size and it might be something you encounter when opening an old project but it's not� Two questions. 1) can working constraints be added programmatically to a NON-AutoLayout environment, in other words, are the safe area guides even there and will constraints work when not using AutoLayout, and 2) is there any other way to *simply* deal with iPhone X (without AutoLayout in IB and the safe area guides)?

I recommend using this framework for building constraint based layouts programmatically, it makes the process straightforward and faster. Take the setup for the contentView of this cell for example:

contentView.addSubview(descriptionLabel)
    contentView.addSubview(amountLabel)
    contentView.addSubview(dateLabel)
    contentView.addSubview(bottomRightLabel)

    constrain(descriptionLabel, amountLabel, dateLabel, bottomRightLabel) { desc, amount, date, bottomRight in

        desc.top              == desc.superview!.top + 16
        desc.left             == desc.superview!.left + 16
        desc.right            <= amount.left + 12
        desc.bottom           == date.top - 12

        amount.centerY        == desc.centerY
        amount.right          == amount.superview!.right - 12

        date.left             == date.superview!.left + 16
        date.right            <= bottomRight.left - 12
        date.bottom           == date.superview!.bottom - 16

        bottomRight.centerY   == date.centerY
        bottomRight.right     == bottomRight.superview!.right - 12
    }

Building an App with only code using Auto Layout, Learn how to make your iOS app's UI in code using Auto Layout Implementing Auto Layout programmatically is a great solution to these problems. In this tutorial, you'll make a Gallery App using programmatic constraints. Programmatically Creating Constraints. Whenever possible, use Interface Builder to set your constraints. Interface Builder provides a wide range of tools to visualize, edit, manage, and debug your constraints. By analyzing your constraints, it also reveals many common errors at design time, letting you find and fix problems before your app even runs.

Working with Auto Layout Visual Format Language and , Most people prefer the graphical way to set the constraints, working are added to the superview, and not to the view that constraints concern. Having made our introduction on how to set constraints programmatically, let's� Note: Without this property, AutoLayout will NOT work… I have made mistakes by not adding them and wondered why nothing showed up on the viewscreen. Then… • Create a method called setUpAutoLayout() so that I do not have to write constraints code inside ViewDidLoad function.

How to make Auto Layout more convenient in iOS, The problem is that we are using equalToConstant , not equalTo . The generic constraints of NSLayoutAnchor is giving us misleading errors� Working with Constraints in Interface Builder. There are three main options for setting up Auto Layout constraints in Interface Builder: You can control-drag between views, you can use the Pin and Align tools, and you can let Interface Builder set up the constraints for you and then edit or modify the results.

Programmatic Layout Constraints in Xamarin.iOS, This guide presents working with iOS Auto Layout constraints in C# are not tied to a particular position on the screen, constraints help create For example, when using dynamically created UI elements added to a UIView . Pay special attention that the constraints are added to the superview, and not to the view that constraints concern. And here it’s coming a general rule that you should always have in mind; when having simple views (like here) which do not relate to any other custom views, then the constraints you create for it are added to its parent view.

Comments
  • It's much simpler to use anchor constraints in code.
  • Don't add constraints in layoutSubviews. You'll end up adding duplicate constraints over and over every time the view is laid out. Do it in buildView instead.
  • I think you were on the right track with setting translatesAutoresizingMaskIntoConstraints to false, but you should only set that to false for the subviews that you've created, not the cell itself nor the cell's contentView. Try setting it to false just for imageContainer, rightImageView, activityIndicator, and valueLabel. If this fixes your issue (I'm not 100% sure it will), then I'll add this as an answer.
  • few comments: (1)you need to set constraints when the cell is created, not in layoutSubviews (2) You're setting top, bottom and centreY constraints to the container - if you are anchoring top & bottom you don't need to do the centre (3) use anchors as they're far easier to read and debug (4) if you're setting all priorities to the same, then there's no point setting them (5) you don't seem to have set any size or leading constraint for the label. I'll have a crack at rewriting them as anchors below and try to address these.
  • @CheshireChild Still need example code with anchors etc or you OK now?