What I'm trying to do in my project is to transfer images to the screen according to the location data coming from the firebase( for example x = 5 , y = 10, width = 30, height = 50). For example, let's say I have 10 images to display (maybe even 100 images). The first of these images should be at the top. Each incoming image must be below the previous one but image can be different in x and y axis. I tried to assign different constraint with a for loop to the image that I have defined only one. But my problem is I get the following constraint error. Can you help me how can I do this? The image that should be is as follows. The image here. My simulator shows only one view like this image.
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:0x600000cd4dc0 UIView:0x12b304a70.height == 50 (active)>",
"<NSLayoutConstraint:0x600000cd51d0 V:[UIView:0x12b304a70]-(60)-[UIView:0x12b304a70] (active)>"
)
My code:
let View: UIView = {
let view = UIView()
view.backgroundColor = .red
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
var count = 1
var topAnchor: NSLayoutYAxisAnchor?
for views in 1...11{
if count == 1{
view.addSubview(View)
View.anchor(top: view.safeAreaLayoutGuide.topAnchor, bottom: nil, leading: nil, trailing: nil, paddingTop: 10, paddingBottom: 0, paddingLeft: 0, paddingRight: 0, width: 50, height: 50)
View.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
topAnchor = View.bottomAnchor
count += 1
}
else{ // if count
view.addSubview(View)
View.anchor(top: topAnchor, bottom: nil, leading: nil, trailing: nil, paddingTop: 60, paddingBottom: 0, paddingLeft: 0, paddingRight: 0, width: 30, height: 30)
View.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
topAnchor = View.topAnchor
}
}
With this extension:
extension UIView{
func anchor(top: NSLayoutYAxisAnchor?,
bottom: NSLayoutYAxisAnchor?,
leading: NSLayoutXAxisAnchor?,
trailing: NSLayoutXAxisAnchor?,
paddingTop: CGFloat,
paddingBottom: CGFloat,
paddingLeft: CGFloat,
paddingRight: CGFloat,
width: CGFloat,
height: CGFloat
){
if let top = top{
self.topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true
}
if let bottom = bottom{
self.bottomAnchor.constraint(equalTo: bottom, constant: paddingBottom).isActive = true
}
if let leading = leading{
self.leadingAnchor.constraint(equalTo: leading, constant: paddingLeft).isActive = true
}
if let trailing = trailing{
self.trailingAnchor.constraint(equalTo: trailing, constant: paddingRight).isActive = true
}
if width != 0{
widthAnchor.constraint(equalToConstant: width).isActive = true
}
if height != 0{
heightAnchor.constraint(equalToConstant: height).isActive = true
}
}
}
A few observations:
As Geoff Hackworth pointed out, you are creating only one subview (one that was instantiated once with a closure). You really want to have a method that creates a new subview every time.
In the
elseblock, you are setting the top anchor of every subsequent view to be the top anchor of the preceding view. You presumably wanted to set the next view’s top anchor to be relative to the preceding view’s bottom anchor.As a minor detail, you are not setting the bottom anchor of the last view. Generally we want our constraints to be fully defined, so I would suggest adding a
bottomAnchorfor the last subview. This is especially true in self-sizing cells, that need an unambiguous set of vertical constraints.So, perhaps:
And, if you forgive me, I tweaked the
UIViewextension:In the above, I have also:
Simplified the
forloop so we do not need theif-elsebased upon the counter.I have given the
UIViewextension default values for its parameters, so you do not need to supply parameters ofnilat the call point.Needless to say, we often would consider a
UIStackView:That having been said, stack views within cells don’t always work perfectly, so you might have to resort to the prior technique.