Skip to content

Latest commit

 

History

History

day-030

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

Day 30: Project 6, Part One

Follow along at https://www.hackingwithswift.com/100/30.

📒 Field Notes

This day covers the first part of Project 6: Auto Layout in Hacking with Swift.

I have a separate repository where I've been creating projects alongside the material in the book. And you can find Project 6 here. However, I also copied it over to this day's folder so I can extend from where I left off.

With that in mind, Day 30 focuses on several specific topics:

  • Advanced Auto Layout
  • Auto Layout in code: addConstraints() with Visual Format Language

Advanced Auto Layout

Using Auto Layout to get our vertical stack of flags viewable — all at once — in landscape mode comes with some nuance.

Initially setting the "Bottom Space to Safe Area" constraint on the bottom flag (I tend to think of this process as "pinning") gives it a fixed, constant amount of spacing with a Relation of Equal. This leads to Auto Layout stretching or squeezing content in order to meet those demands — and in this case, the flags get squeezed to 0 in landscape mode (because the constant value is greater than the height of the entire screen!).

And there's a lesson in that: Auto Layout constraints can be used for flexibility — but they can also be used for precision and concreteness. We want the flexibility.

By changing the Relation from Equal to Greater Than or Equal, and the Constant to 20, we unlock just that. Alas, it's still not perfect — Auto Layout still squashes one flag in the middle — But Auto Layout has options now. And we only need a few more tweaks on top:

  • Set each flag to be of Equal Heights with respect to its adjacent flag. Now an odd flag won't be resized.
  • Add the Aspect Ratio constraint to each flag, internally, so that width will be resized in accordance with any changes to height.

Presto 💥

Auto Layout Landscape

Auto Layout in code: addConstraints() with Visual Format Language

Apple's documentation provides a handy description of the full specification, but the core idea is that VFL allows us to programmatically (thus, dynamically) define horizontal and vertical layout, alignment, and sizing constraints for views that might otherwise not be possible — or straightforward — in Interface Builder.

Using a string like this...

V:|[label1(labelHeight@999)]-[label2(label1)]-[label3(label1)]-[label4(label1)]-[label5(label1)]->=10-|

... we can encode an immense amount of information: direction, alignment, element sizing, element spacing, edge offsets, and event constraint priority levels (designated above by the @999).

Actually activating these constraints for a view can get a bit verbose, since we need to make use of NSLayoutConstraint, but it's not too bad if we organize values in variables:

view.addConstraints(
    NSLayoutConstraint.constraints(
        withVisualFormat: layoutString,
        options: [],
        metrics: metrics,
        views: labelViews
    )
)

Some important pointers and code architecture:

  • Views need to be structured as a dictionary. VFL processes this dictionary and makes use of the key names to interpret its string.
  • For views that we're using VFL with, translatesAutoresizingMaskIntoConstraints needs to be set to false. It's true by default for any view created programmatically — but we'll be writing the constraints, thank you very much 😀.
  • Vertical pipes | refer to edges, and omitting them or adding them can makes the difference between items being stretched end-to-end or not.

🔗 Additional/Related Links