SwiftUI: Embracing the nonobvious?

This is going to be another day where I get to play with SwiftUI because I can’t get any real work done right now and am dealing with lots of interruptions.

This morning, I returned to yesterday’s mouse inventory sample to try to get my rounded corners working. Several people suggested that I implement my interface using a ZStack and a Rectangle, so I tried that first.

To my surprise, the Rectangle expanded my VStack and I haven’t to date figured out how to constrain its size to be no more than its sibling. I wanted the rectangle to grow weakly instead of pushing the title and total items towards the edge of the parent view, the way it did in this screenshot:

Here’s what it looks like without the monster-sized Rectangle, which I think is a much more appealing layout:

So instead, after messing around a bit, it occurred to me that everything is a view or at least everything is kind of view-ish and if so, then I could possibly apply my corner rounding to Color, which I did.

}.padding()
.background(Color.white.cornerRadius(8))

And surprise, this is what I got:

Isn’t that cool?

Although the final layout is exactly what I wanted, if you think about it, it’s not that intuitive that system uses tight placement for this and lax spacing for the one with the Rectangle.

In fact, as a developer, I’m not happy about not having direct control over the tightness of either layout or an obvious way to relate ZStack siblings. If there’s a way to describe how much content hugging I want in a ZStack layout and how to prioritize which item in that layout should guide the others, I haven’t discovered it. If you have, please let me know!

I’m still trying to learn to best use the deeply mysterious Length (and, no, don’t tell me “it’s just CGFloat“, because clearly it isn’t “just” that with all the Angle, Anchor, GeometryProxy, UnitPoint stuff,  and so forth) and apply layout relationships. Today, time allowing, I’d certainly like to learn more about the mysterious TupleView, a View created from a swift tuple of View values and see where it is used, the ForEach, which computes views on demand, Groups, EquatableView, and so forth.

3 Comments

  • You’re correct. According to one of the WWDC SwiftUI videos each of those parameters is indeed a View.

    .padding()
    .background(Color.white.cornerRadius(8))

    Both views. Crazy!

    Another thing I learned here is that SwiftUI controls don’t map to UIViews or NSViews but are rendered by low level CGDrawing apis.

    Super exciting all this…

    – Rob

    • I still haven’t had time to watch anything beyond the first few minutes of a single SwiftUI video. 🙁 Real life, work. Yesterday and today, I’m taking care of some family stuff so I’m not on a normal clock.

  • Layout is going to create so many headaches. I’ve just found out that setting the frame on an HStack does nothing in macOS (the default window size is tiny); and you have to add a Spacer() inside your stack to get the full width, at which point the window autoexpands.

    (I fell at the hurdle of Image(systemName: “desktopcomputer”) because that’s not available on macOS in b2, Also, Mask(Circle()) gives me a square image.)

    On macOS the rectangle just does not show up at all; if you set a frame for it, it confuses swiftUI – suddenly ‘Mouse Stocks’ is ambiguous. (On closer examination, Rectangle() fills its super-View.

    setting a frame for the ZStack worked for me: now the rectangle has the dimensions I wanted, and it shows up with nicely rounded corners and all is well.

    As a side-effect, however, I can no longer resize my window.