Reputation: 434
Can anyone provide insight on why my code isn't working?
I'm trying to add horizontal spacing between the 2 views in the picture (Red and Black one) but for some reason I keep getting that error and I'm not sure how to fix it.
I'm assuming the other constraints are working correctly since I'm not seeing any issues, nor in the simulation or in the console.
Code as requested by user: https://gist.github.com/sungkim23/66ecd9ce71d0480f083bcd05caf0a58c
import UIKit
class BuyButton: UIView {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
//MARK: - View
backgroundColor = UIColor(red: 180/255, green: 35/255, blue: 115/255, alpha: 1)
layer.cornerRadius = 3
//MARK: - Price View
let priceView = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: bounds.size.height))
priceView.backgroundColor = UIColor.black
addSubview(priceView)
//MARK: - Purchase View
let purchaseView = UIView(frame: CGRect(x: 80, y: 0, width: bounds.size.width - 80, height: bounds.size.height))
purchaseView.backgroundColor = UIColor.red
addSubview(purchaseView)
//MARK: - Price Label
let priceLabel = UILabel(frame: CGRect.zero)
priceLabel.text = "$ 50.00"
priceLabel.textAlignment = .center
priceLabel.backgroundColor = .red
priceLabel.translatesAutoresizingMaskIntoConstraints = false
priceView.addSubview(priceLabel)
//MARK: - Purchase Label
let purchaseLabel = UILabel(frame: CGRect.zero)
purchaseLabel.text = "Purchase"
purchaseLabel.textAlignment = .center
purchaseLabel.backgroundColor = .green
purchaseLabel.translatesAutoresizingMaskIntoConstraints = false
purchaseView.addSubview(purchaseLabel)
//MARK: - View Constraints
priceView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
priceView.topAnchor.constraint(equalTo: topAnchor).isActive = true
priceView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
purchaseView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
purchaseView.topAnchor.constraint(equalTo: topAnchor).isActive = true
purchaseView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
priceView.centerXAnchor.constraint(equalTo: purchaseView.centerXAnchor).isActive = true
//MARK: - Label Constraints
priceLabel.centerXAnchor.constraint(equalTo: priceView.centerXAnchor).isActive = true
priceLabel.centerYAnchor.constraint(equalTo: priceView.centerYAnchor).isActive = true
purchaseLabel.centerXAnchor.constraint(equalTo: purchaseView.centerXAnchor).isActive = true
purchaseLabel.centerYAnchor.constraint(equalTo: purchaseView.centerYAnchor).isActive = true
//MARK: - Constraint priorities
}
}
UPDATE 1 - Added error to question as requested
2017-03-13 11:02:38.440892 ButtonTest[20954:1645749] [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.
(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSAutoresizingMaskLayoutConstraint:0x60000009a400 h=--& v=--& UIView:0x7fe55be017b0.midX == 40 (active)>",
"<NSAutoresizingMaskLayoutConstraint:0x600000099ff0 h=--& v=--& UIView:0x7fe55bc09310.midX == 232 (active)>",
"<NSLayoutConstraint:0x600000099c30 UIView:0x7fe55be017b0.centerX == UIView:0x7fe55bc09310.centerX (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600000099c30 UIView:0x7fe55be017b0.centerX == UIView:0x7fe55bc09310.centerX (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
UPDATE 2 - tl;dr
Use
yourView.leadingAnchor.constraint(equalTo: yourOtherView.trailingAnchor).isActive = true
instead of
yourView.centerXAnchor.constraint(equalTo: yourOtherView.centerXAnchor).isActive = true
Upvotes: 0
Views: 4279
Reputation: 77651
OK, from your comment on Matt's question. You're still not thinking in constraints :D
You don't need a bounds.size.width - 80
that is a frame
and rect
thing to think about. It is not an AutoLayout
thing to think about.
In order to think about layouts in AutoLayout you need to be describing the layout to the app.
This is what I think you want...
From this list there is only one possible layout for the price view and purchase view. Any other layout would contradict the constraints. Also, I haven't added anything I don't need. For instance, the centerYAnchor
of both views will be the same by following these instructions. I don't need to explicitly add that.
So now you have this very simple description... just add it.
// set the width of price view
priceView.widthAnchor.constraint(equalToConstant: 80).isActive = true
// now add the other edges to super view
priceView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
priceView.topAnchor.constraint(equalTo: topAnchor).isActive = true
priceView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
// set the spacing between price view and purchase view
purchaseView.leadingAnchor.constraint(equalTo: priceView.trailingAnchor).isActive = true
// add the other edges to the super view
purchaseView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
purchaseView.topAnchor.constraint(equalTo: topAnchor).isActive = true
purchaseView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
That should be it (for the price view and purchase view).
Don't try to overcomplicate your task when using AutoLayout. A lot of the work is done for you by AutoLayout.
Edit - UIStackView
As per @abizern's comment on your question. You should really check out UIStackView
. It takes away a lot of this pain and makes layouts using auto layout much easier.
Upvotes: 4
Reputation: 535547
Problem 1: You never said
priceView.translatesAutoresizingMaskIntoConstraints = false
Problem 2: You never said
purchaseView.translatesAutoresizingMaskIntoConstraints = false
Problem 3: You need a complete set of constraints on priceView
and purchaseView
.
In other words, you cannot mix and match like this, using frame
for some views and autolayout for others. Once a view is involved in autolayout, it is completely involved in autolayout and must be entirely positioned and sized by autolayout.
So, if you fix problem 1 and problem 2, no more console errors — but then you will find that the positions / sizes of the views go crazy, because you have gone from overdetermined layout to underdetermined layout. Now you need to fill in the missing constraints to determine that layout. In particular:
The black view's width will need to be determined (priceView
).
The red view's width and x-position will need to be determined (purchaseView
).
Upvotes: 2