Does a view need to be init with a frame and then have auto-layout change it or just use auto-layout?

Viewed 2577

I have a custom view that I have implemented and I am trying to learn how to use auto-layout without the use of the storyboard.

My question is do I need to init my view with a frame, or can I just do an empty init and then use auto layout to have the view figure out the width and height by itself?

Below you will see that I have tried adding the frame and then putting the auto-layout thinking that I have to put a frame first and then auto-layout changes it.

let origin = CGPoint(x: 0.0, y: 0.0)
let size = CGSize(width: view.frame.width, height: 44.0)

let frame = CGRect(origin: origin, size: size)

customView = ExpandableHeadingView(frame: headingFrame)

customView.frame.size.height = 44.0

view.addSubview(customView)

view.topAnchor.constraint(equalTo: customView.topAnchor).isActive = true
view.leftAnchor.constraint(equalTo: customView.leftAnchor).isActive = true
view.rightAnchor.constraint(equalTo: customView.rightAnchor).isActive = true
view.heightAnchor.constraint(equalTo: customView.heightAnchor).isActive = true
3 Answers

If you are overriding the init method on a custom UIView subclass (the one that receives a frame as its only argument) you will have to give it a frame when creating it in a ViewController. What you can do is give it an empty frame and the with AutoLayout set its proper constraints for position and size. For example:

class CounterView: UIView {
  override init(frame: CGRect) {
      super.init(frame: frame)
      translatesAutoresizingMaskIntoConstraints = false
      backgroundColor = .red
  }

  required init?(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
  }
}

And in the view controller:

private var counterView: CounterView = {
  let view = CounterView(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
  return view
}()

.....

view.addSubview(counterView)
counterView.leadingAnchor.constraint(equalTo: margin.leadingAnchor).isActive = true
counterView.trailingAnchor.constraint(equalTo: margin.trailingAnchor).isActive = true
counterView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: standardSpacing).isActive = true
counterView.heightAnchor.constraint(equalToConstant: 200).isActive = true

That code produces this:

Simulator Screenshot

Related