1

I'm working on a Swift project and there is one thing I'm not clear about making UIs programmatically. I tried to display a simple UIView on the screen.

lazy var container: UIView = {
    let view = UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
    view.backgroundColor = UIColor.systemImageGray()
    view.layer.cornerRadius = view.layer.bounds.width / 2
    view.clipsToBounds = true
    return view
}()

override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(container)
    setupConstraints()
}

func setupConstraints() {
    container.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        container.topAnchor.constraint(equalTo: self.topAnchor, constant: 14),
        container.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -14),
        container.widthAnchor.constraint(equalToConstant: 30),
        container.heightAnchor.constraint(equalToConstant: 30)
    ])
}

The code above works fine, but since I set the with and height twice, I feel it's redundant, like UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30)) and set the width and height constraints in setupConstraints.

Since I set the width and height in UIView's frame, I thought I don't need to set the width and height constraints in the setupConstraints, but it doesn't show the view unless I add the width and height constraints again. So in this case, why I cannot set the width and height in UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30)) and I also have to add the width/height constraints again?

Yuuu
  • 715
  • 1
  • 9
  • 32

1 Answers1

3

frame is useful when you are not using the Autolayout engine to place your views.

When you do:

container.translatesAutoresizingMaskIntoConstraints = false

You are explicitly telling the engine to ignore the frame & that you are responsible for applying a new set of constraints.

And hence you eventually do:

NSLayoutConstraint.activate([
    container.topAnchor.constraint(equalTo: self.topAnchor, constant: 14),
    container.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -14),
    container.widthAnchor.constraint(equalToConstant: 30),
    container.heightAnchor.constraint(equalToConstant: 30)
])

Which sets the positioning & dynamic sizing as per Autolayout's expectations.


translatesAutoresizingMaskIntoConstraints

A Boolean value that determines whether the view’s autoresizing mask is translated into Auto Layout constraints.

Ref: https://developer.apple.com/documentation/uikit/uiview/1622572-translatesautoresizingmaskintoco

staticVoidMan
  • 19,275
  • 6
  • 69
  • 98
  • Thank you so much for the quick response! Now I understood why it did not work. Yeah, at first, I tired with let view = UIView(), however, it won't make the view a circle shape since I adjust the corner radius right after that code ( view.layer.cornerRadius = view.layer.bounds.width / 2). Is there other ways to add corner radius when I use let view = UIView() one? I guess I can use viewdidlayoutsubviews or something, but I'll make my project as the MVC pattern, so if possible I want to put the corner radius stuff in the lazy var property. – Yuuu Oct 18 '21 at 05:37
  • 1
    @Yuuu Aah, I didn't notice that you have a `layer.cornerRadius` modification. In this case, if you know the height & width are constant then what you have done so far by providing the frame is perfectly fine. But if the height & width were dynamic then I'd put this in the `layoutSubviews`. [Also see this](https://stackoverflow.com/q/30348901/2857130) – staticVoidMan Oct 18 '21 at 06:02