AutoResizing in XCODE Swift (iOS & MacOS)

Autoresizing is a matter of conceptually assigning a subview “springs and struts.” A spring can expand and contract; a strut can’t. Springs and struts can be assigned internally or externally, horizontally or vertically. With two internal springs or struts, you specify whether and how the view can be resized; with four external springs or struts, you specify whether and how the view can be repositioned:

  • Imagine a subview that is centered in its superview and is to stay centered, but is to resize itself as the superview is resized. It would have four struts externally and two springs internally.
  • Imagine a subview that is centered in its superview and is to stay centered, and is not to resize itself as the superview is resized. It would have four springs externally and two struts internally.
  • Imagine an OK button that is to stay in the lower right of its superview. It would have two struts internally, two struts externally from its right and bottom, and two springs externally from its top and left.
  • Imagine a text field that is to stay at the top of its superview. It is to widen as the superview widens. It would have three struts externally and a spring from its bottom; internally it would have a vertical strut and a horizontal spring.

In code, a combination of springs and struts is set through a view’s autoresizingMask property, which is a bitmask (UIView.AutoresizingMask) so that you can combine options. The options represent springs; whatever isn’t specified is a strut. The default is the empty set, apparently meaning all struts — but of course it can’t really be all struts, because if the superview is resized, something needs to change, so in reality an empty autoresizingMask is the same as .flexibleRightMargin together with .flexibleBottomMargin, meaning the view is pinned by struts to the top left.

In debugging, when you log a UIView to the console, its autoresizingMask is reported using the word autoresize and a list of the springs. The external springs are LMRMTM, and BM; the internal springs are W and Hautoresize = LM+TM means there are external springs from the left and top; autoresize = ​W⁠+BM means there’s an internal horizontal spring and a spring from the bottom.

Autoresize subviews when the frame of superview is modified - Stack Overflow
Fig. Auto-resizing in Swift Xcode

To demonstrate autoresizing, I’ll start with a view and two subviews, one stretched across the top, the other confined to the lower right (Figure 1-13):

let v1 = UIView(frame:CGRect(100, 111, 132, 194))
v1.backgroundColor = UIColor(red: 1, green: 0.4, blue: 1, alpha: 1)
let v2 = UIView(frame:CGRect(0, 0, 132, 10))
v2.backgroundColor = UIColor(red: 0.5, green: 1, blue: 0, alpha: 1)
let v1b = v1.bounds
let v3 = UIView(frame:CGRect(v1b.width-20, v1b.height-20, 20, 20))
v3.backgroundColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1)
self.view.addSubview(v1)
v1.addSubview(v2)
v1.addSubview(v3)
pios 1412

To that example, I’ll add code applying springs and struts to the two subviews to make them behave like the text field and the OK button I was hypothesizing earlier:

v2.autoresizingMask = .flexibleWidth
v3.autoresizingMask = [.flexibleTopMargin, .flexibleLeftMargin]

Now I’ll resize the superview, bringing autoresizing into play; as you can see (Figure 1-14), the subviews remain pinned in their correct relative positions:

v1.bounds.size.width += 40
v1.bounds.size.height -= 50
pios 1413

If auto resizing isn’t sophisticated enough to achieve what you want, you have two choices:

  • Combine it with manual layout in layoutSubviews. Autoresizing happens before layoutSubviews is called, so your layoutSubviews code is free to come marching in and tidy up whatever autoresizing didn’t get quite right.
  • Use autolayout. This is actually the same solution, because autolayout is in fact a way of injecting functionality into layoutSubviews. But using autolayout is a lot easier than writing your own layoutSubviews code!

Written by

XR Developer responsible for end-to-end development of XR solutions spanning multiple domains, by using various XR and WebXR libraries.

Leave a Reply