For a project I needed to add a UIPickerView with custom cells using AutoLayout. UIKit allows this via the UIPickerViewDelegate method pickerView(_:viewForRow:forComponent:reusingView).
The cell just needed an UIImageView and UILabel, so I thought it would be pretty straightforward to do, but there are some caveats you need to know. Big thanks to Tom Adriaenssen for pointing them out and not ruining my Sunday afternoon 🙂
The problem
This is what the problem looked like
I’ve added the following constraints:
- UILabel: center in superview (horizontal, vertical)
- UIImageView: Pin the Trailing edge to the Leading edge of the UILabel with an offset of -20
- UIImageView: center in superview (vertically)
- As the custom cell gets embedded into the UIPickerView I also pinned all 4 edges of my custom view to the superview with no insets
- I set thesetTranslatesAutoresizingMaskIntoConstraints method to false on my custom cell
The code looked like this
//
// CustomPickerRowView.swift
// CustomUIPickerCell
//
// Created by Frederik Jacques on 05/07/15.
// Copyright (c) 2015 Frederik Jacques. All rights reserved.
//
import UIKit
import PureLayout
class CustomPickerRowView: UIView {
// MARK: - IBOutlets
// MARK: - Properties
let rowData:RowData
var imageView:UIImageView!
var label:UILabel!
var didSetupConstraints:Bool = false
// MARK: - Initializers methods
init(frame: CGRect, rowData:RowData) {
self.rowData = rowData
super.init(frame: frame)
backgroundColor = UIColor.purpleColor()
self.setTranslatesAutoresizingMaskIntoConstraints(false)
createImageView()
createLabel()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Lifecycle methods
override func updateConstraints() {
if( !didSetupConstraints ) {
self.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsetsZero)
label.autoCenterInSuperview()
imageView.autoConstrainAttribute(.Horizontal, toAttribute: .Horizontal, ofView: self)
imageView.autoPinEdge(.Trailing, toEdge: .Leading, ofView: label, withOffset: -10)
}
super.updateConstraints()
}
// MARK: - Private methods
private func createImageView(){
imageView = UIImageView.newAutoLayoutView()
imageView.image = UIImage(named: rowData.imageName)
addSubview(imageView)
}
private func createLabel(){
label = UILabel.newAutoLayoutView()
label.backgroundColor = UIColor.redColor()
label.text = rowData.title
addSubview(label)
}
}
SwiftThe solution
So doing the following resulted in the BAD! version of the image above. What did I do wrong?
First of all, you should _not_ set setTranslatesAutoresizingMaskIntoConstraints to false when you are using AutoLayout within a view which you don’t place (the UIPickerView will take care of this).
Second, don’t pin the edges of the custom cell to the superview! The UIPickerView will figure out the height.
And the most important part I forgot, you should call setNeedsUpdateConstraints() at the end of the init method!
You can check out the project on GitHub to see a working version.