I have a subclass of UITableViewCell that uses AutoLayout and is reused through UITableView registerNib(nib: UINib, forCellReuseIdentifier: String)
and dequeueReusableCellWithIdentifier(identifier: String)
. The cell has two buttons and I set the AutoLayout constraints on layoutSubviews()
:
override func layoutSubviews()
{
super.layoutSubviews()
//Clear all constraints from the cell
self.contentView.removeConstraints(self.contentView.constraints())
self.oneButton.setTranslatesAutoresizingMaskIntoConstraints(false)
self.twoButton.setTranslatesAutoresizingMaskIntoConstraints(false)
let viewsDict : [NSObject: AnyObject] = ["oneButton" : self.oneButton, "twoButton": self.twoButton]
//Setting the constraints
self.contentView.addConstraint(NSLayoutConstraint(item: self.oneButton, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: self.twoButton, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0.0))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-25-[oneButton]-25-[twoButton]-25-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-25-[oneButton(40)]-25-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-25-[twoButton(40)]-25-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
}
This works only for the first time the cell is instantiated. After it is reused the horizontal spacing and sizing breaks. After playing around and setting breakpoints I found out that updateConstraints
is called after layoutSubviews
and only the first time the cell is instantiated, not after reused.
After a little bit more fiddling around I tried this:
override func updateConstraints()
{
super.updateConstraints()
self.hasUpdated = true
}
override func layoutSubviews()
{
super.layoutSubviews()
if (!self.hasUpdated)
{
//Clear all constraints from the cell
self.contentView.removeConstraints(self.contentView.constraints())
self.oneButton.setTranslatesAutoresizingMaskIntoConstraints(false)
self.twoButton.setTranslatesAutoresizingMaskIntoConstraints(false)
let viewsDict : [NSObject: AnyObject] = ["oneButton" : self.oneButton, "twoButton": self.twoButton]
//Setting the constraints
self.contentView.addConstraint(NSLayoutConstraint(item: self.oneButton, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: self.twoButton, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0.0))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-25-[oneButton]-25-[twoButton]-25-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-25-[oneButton(40)]-25-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-25-[twoButton(40)]-25-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
}
}
And now it works as expected, but I feel that I'm maybe inhibiting some reuse layout mechanic, since I'm not always setting the constraints. Any thoughts about this?
EDIT: After Shai comment down bellow, I thought that the removeConstraints
and setTranslatesAutoresizingMaskIntoConstraints
calls could be the culprits. What I did then was stop overriding layoutSubviews
and changing it to:
override func awakeFromNib()
{
super.awakeFromNib()
self.contentView.removeConstraints(self.contentView.constraints())
self.oneButton.setTranslatesAutoresizingMaskIntoConstraints(false)
self.twoButton.setTranslatesAutoresizingMaskIntoConstraints(false)
// Initialization code
}
override func updateConstraints()
{
super.updateConstraints()
let viewsDict : [NSObject: AnyObject] = ["oneButton" : self.oneButton, "twoButton": self.twoButton]
//Setting the constraints
self.contentView.addConstraint(NSLayoutConstraint(item: self.oneButton, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: self.twoButton, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0.0))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-25-[oneButton]-25-[twoButton]-25-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-25-[oneButton(40)]-25-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-25-[twoButton(40)]-25-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
}
And now I don't feel like hacking reuse mechanics... Still, any thoughts on this?