Roman Roman - 4 months ago 16
Swift Question

swift ios adding constraints for several subviews with a loop

I am newcomer in swift and tried to learn how to add several subviews and their constraints using a loop. I tried to follow some answer to similar questions but it is not working. Could you help me with my code? Thank you in advance.

Here is my code:

let card = UIView()

let view2 = UIView()

view2.backgroundColor = UIColor.greenColor()

view2.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(view2)

let leftSideConstraint3 = NSLayoutConstraint(item: view2, attribute: .Left, relatedBy: .Equal, toItem: view, attribute: .Left, multiplier: 1, constant: 0.0)
let topConstraint3 = NSLayoutConstraint(item: view2, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1, constant: 0.0)
let widthConstraint3 = NSLayoutConstraint(item: view2, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 1, constant: 0.0)
let heightConstraint3 = NSLayoutConstraint(item: view2, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Height, multiplier: 1, constant: 0.0)
view.addConstraints([leftSideConstraint3, topConstraint3, heightConstraint3, widthConstraint3])



var cards = [UIView](count: 16, repeatedValue: card) // array with 16 cards



card.layer.borderWidth = 3
card.layer.borderColor = UIColor.blackColor().CGColor
card.backgroundColor = UIColor.orangeColor()



var columnCounter:Int = 0
var rowCounter:Int = 0


//Loop through each card in the array
for index in 0...cards.count-1 {



// place the card in the view and turn off translateAutoresizingMask
let thisCard = cards[index]
thisCard.translatesAutoresizingMaskIntoConstraints = false
view2.addSubview(thisCard)

//set the height and width constraints
let widthConstraint = NSLayoutConstraint(item: thisCard, attribute: .Width, relatedBy: .Equal, toItem: view2, attribute: .Width, multiplier: 0.25, constant: 0)
let heightConstraint = NSLayoutConstraint(item: thisCard, attribute: .Height, relatedBy: .Equal, toItem: view2, attribute: .Height, multiplier: 0.25, constant: 0)
view2.addConstraints([heightConstraint, widthConstraint])

//set the horizontal position

if (columnCounter > 0) {

// card is not in the first column
let cardOnTheLeft = cards[index-1]

let leftSideConstraint = NSLayoutConstraint(item: thisCard, attribute: .Left, relatedBy: .Equal, toItem: cardOnTheLeft, attribute: .Right, multiplier: 1, constant: 0)

//add constraint to the contentView
view2.addConstraint(leftSideConstraint)

} else {

//card is in the first column

let leftSideConstraint = NSLayoutConstraint(item: thisCard, attribute: .Left, relatedBy: .Equal, toItem: view2, attribute: .Left, multiplier: 1, constant: 0)

//add constraint to the contentView
view2.addConstraint(leftSideConstraint)

}


//set the vertical position

if (rowCounter > 0) {

// card is not in the first row
let cardOnTop = cards[index-4]

let topConstraint = NSLayoutConstraint(item: thisCard, attribute: .Top, relatedBy: .Equal, toItem: cardOnTop, attribute: .Bottom, multiplier: 1, constant: 0)

// add constraint to the contentView
view2.addConstraint(topConstraint)

} else {

//card is in the first row

let topConstraint = NSLayoutConstraint(item: thisCard, attribute: .Top, relatedBy: .Equal, toItem: view2, attribute: .Top, multiplier: 1, constant: 0)

//add constraint to the contentView
view2.addConstraint(topConstraint)

}



//increment the column counter
columnCounter = columnCounter+1

//if the column counter reaches the fifth column reset it and increase the row counter
if (columnCounter >= 4) {
columnCounter = 0
rowCounter = rowCounter+1
}




} // end of the loop

Answer

This creates an array with 16 references to the same card.

var cards = [UIView](count: 16, repeatedValue: card)

Replace it with:

var cards = (1...16).map { _ in UIView() }

which will result in an array with 16 unique UIViews.