Ancestors

Toot

Written by John Siracusa on 2024-12-18 at 03:31

Welcome to my new series on things I don’t understand about Apple’s premier user interface framework. I’m calling it…

[#]SwiftUWhy

To be clear, these are things I don’t understand, not necessarily things that are “wrong.” They sure look wrong (or at least “suboptimal”) to me! But maybe there are good reasons, and I just don’t know them yet. SwiftUI experts and historians, please tell me!

The first entry is coming up…

=> More informations about this toot | More toots from siracusa@mastodon.social

Descendants

Written by John Siracusa on 2024-12-18 at 03:35

Why in the world does this interface look like this:

.padding(.top, 1)

.padding(.leading, 2)

.padding(.bottom, 3)

.padding(.trailing, 4)

…or this:

.padding(EdgeInsets(top: 1, leading: 2, bottom: 3, trailing: 4))

…instead of the much more idiomatic:

.padding(top: 1, leading: 2, bottom: 3, trailing: 4)

Like, who in the world thought of this foo(.key, value) API interface in a language with named parameters?!

[#]SwiftUWhy

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by soroush on 2024-12-18 at 03:47

@siracusa One reason is because this api doesn't take an Edge, it takes an Edge.Set, which is an option set. This lets you combine them to let you write stuff like .padding(.horizontal, 10) or .padding(.allButTop, 5).

Is that a good enough reason for a less-than-idiomatic api? I leave that to someone else to answer

=> More informations about this toot | More toots from Soroush@mastodon.social

Written by John Siracusa on 2024-12-18 at 03:56

@Soroush It is not! You could support all that and also have a sane named-param call! Guess which one everyone would use…

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by Adam Overholtzer on 2024-12-18 at 04:05

@siracusa It’s also strange that we can specify nil to apply “default” padding:

.padding(.top, nil)

… but EdgeInsets has no equivalent.

=> More informations about this toot | More toots from adam@iosdev.space

Written by Greg Pierce on 2024-12-18 at 04:09

@adam @siracusa It’s magical incantations all the way down, until they’re not magical.

I miss code you can reason about.

=> More informations about this toot | More toots from agiletortoise@mastodon.social

Written by CM Harrington on 2024-12-18 at 04:10

@siracusa ok, possibly the best hashtag ever.

=> More informations about this toot | More toots from octothorpe@mastodon.online

Written by Guy English on 2024-12-18 at 04:13

@siracusa I’ve got bad news for you on the discoverability front.

=> More informations about this toot | More toots from Gte@mastodon.social

Written by John Siracusa on 2024-12-18 at 04:23

@Gte Speaking of discoverability, I spent a while today puzzling over the “documentation” for this method, trying to figure out what it does and where or why one might want to use it.

https://developer.apple.com/documentation/storekit/entitlementtaskstate/map(_:)-8ly3v

But I did “discover” it, I guess. (It was in some sample code from a WWDC session.)

(And, no, I never really did figure it out.)

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by Guy English on 2024-12-18 at 04:37

@siracusa I’ve a lot of appreciation for Swift and SwiftUI. The language has really grown on me. The corresponding UI framework I’ve found a little inscrutable. I’ve been chalking it up to me being old and maybe not picking up new tricks so quickly. But, to be honest, I’m not sure anyone can? It feels like a thing that’s passed down through experience rather than inspection. While better documentation would be terrific I’d love a better synthesized way of knowing what modifiers were possible.

=> More informations about this toot | More toots from Gte@mastodon.social

Written by Jason Howlin on 2024-12-18 at 12:46

@Gte @siracusa Yeah, "what modifiers are possible” is a problem, because they (almost) all are, although they don't all make sense in context.

One of the first things I thought was, “having every single API be a function / modifier on View certainly can't scale for an entire UI framework…”

Anyway, SwiftUI has a big learning curve, but it’s worth it.

=> More informations about this toot | More toots from jasonhowlin@mastodon.social

Written by Steve Tibbett on 2024-12-19 at 14:10

@Gte @siracusa Traditional autocomplete doesn't work well with modifiers, but this is something Copilot is actually pretty good at. Things that are idiomatic but not discoverable.

=> More informations about this toot | More toots from stevex@mastodon.social

Written by Christian Beer on 2024-12-18 at 04:36

@siracusa I suppose someone wanted to support the following:

.padding(.vertical, 8)

.padding(.horizontal, 12)

at all cost? #SwiftUIWhy

=> More informations about this toot | More toots from chbeer@mastodon.social

Written by John Siracusa on 2024-12-18 at 04:42

@chbeer But…

.padding(vertical: 8)

.padding(horizontal: 12)

.padding(vertical: 8, horizontal: 12)

So…why?!

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by Christian Beer on 2024-12-18 at 05:39

@siracusa I know… very good question. I ask that myself often, too.

Also the .buttonStyle(…), .listStyle(…) implementation: even Xcode can‘t understand the complexity most of the time

=> More informations about this toot | More toots from chbeer@mastodon.social

Written by David Anson on 2024-12-18 at 04:42

@siracusa The current design makes it easy to reuse one (or multiple!) EdgeInsets instances. That may be nice for ensuring consistency within a single view?

=> More informations about this toot | More toots from DavidAnson@mastodon.social

Written by John Siracusa on 2024-12-18 at 04:45

@DavidAnson Sure, but you can have that and the more idiomatic version. Guess which one would get more use?

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by marksmith on 2024-12-18 at 04:47

@siracusa I don't like it either. I add this to my projects:

https://gist.github.com/mjmsmith/040ffb4a8536b61bf479ad5b0abeea6e

=> More informations about this toot | More toots from marksmith@mastodon.social

Written by robb on 2024-12-18 at 17:55

@marksmith @siracusa FWIW, that changes the semantics of nil from “platform dependent padding” to “no padding” and if you were to animate from nil to some value, you'd lose the view identity due to the conditional.

Not trying to tell you what to do with your code base, just calling this out for those unaware.

=> More informations about this toot | More toots from dlx@mastodon.social

Written by marksmith on 2024-12-18 at 18:12

@dlx @siracusa I could be misunderstanding, but doesn't it have the same behavior as the built-in padding modifier? (In the image, trailing is applied both ways with the same result.)

=> View attached media

=> More informations about this toot | More toots from marksmith@mastodon.social

Written by robb on 2024-12-18 at 18:15

@marksmith @siracusa This only affects the case where you pass in nil, e.g. .padding(.bottom) which is effectively .padding(.bottom, nil).

=> View attached media

=> More informations about this toot | More toots from dlx@mastodon.social

Written by marksmith on 2024-12-18 at 18:56

@dlx @siracusa Oh yes, you're right. In my modifier, passing nil (implicitly or explicitly) leaves the value alone rather than resetting it to the default.

A bit hacky under the covers, but I could use .nan as the default value in the padding() View extension, and test for .isNaN instead of nil in EdgePaddingModifier. That would make the behaviors match.

=> More informations about this toot | More toots from marksmith@mastodon.social

Written by robb on 2024-12-18 at 19:01

@marksmith @siracusa yeah, if you think that's worth it.

=> More informations about this toot | More toots from dlx@mastodon.social

Written by Doug on 2024-12-18 at 19:05

@dlx @marksmith @siracusa Should be easy enough to fix the animations by summing the values into a single EdgeInsets to remove the conditional too :)

=> More informations about this toot | More toots from digitalfx@mastodon.social

Written by Doug on 2024-12-18 at 19:06

@dlx @marksmith @siracusa Ah, although that would then conflict with the .nan default 😕

=> More informations about this toot | More toots from digitalfx@mastodon.social

Written by marksmith on 2024-12-18 at 19:11

@digitalfx @dlx @siracusa It's enough to make you think Apple had reasons for doing it the way they did in the first place. :)

=> More informations about this toot | More toots from marksmith@mastodon.social

Written by John Siracusa on 2024-12-18 at 19:47

@marksmith It’s not! There’s no reason to bend over backwards to match the weird functionality of an existing API when adding new, more idiomatic versions. The weird versions still exist for the people who want them!

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by Mike Apurin on 2024-12-18 at 05:03

@siracusa one thing is that in most cases composing padding like that helps convey intent. If I want padding around edges, but more on left/right

.padding(8)

.padding(.horizontal, 8)

reads better than

.padding(top: 8, leading: 16, bottom: 8, trailing: 16)

=> More informations about this toot | More toots from auramagi@hachyderm.io

Written by John Siracusa on 2024-12-18 at 05:06

@auramagi .padding(horizontal: 16, vertical: 8)

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by Mike Apurin on 2024-12-18 at 05:08

@siracusa how many overloads for a simple padding do we need? ;)

=> More informations about this toot | More toots from auramagi@hachyderm.io

Written by John Siracusa on 2024-12-18 at 05:14

@auramagi At least one more!

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by Joseph Humfrey on 2024-12-18 at 06:37

@siracusa @auramagi one more? Well I often use:

.padding([.top, .bottom], 5)

But only because I didn’t know about .vertical!

=> More informations about this toot | More toots from joethephish@mastodon.gamedev.place

Written by Harshil Shah :psyduck: on 2024-12-18 at 05:09

@siracusa My guess would be because this forces you to declare padding for all edges (if it’s one modifier) or is going to mess up diagnostics and type checking and stuff if they let you pick and choose because that would require multiple modifier variants

=> More informations about this toot | More toots from harshil@mastodon.social

Written by Harshil Shah :psyduck: on 2024-12-18 at 05:12

@siracusa Also fwiw I think the EdgeSet variant is pretty good cause it also lets you do things just horizontal and vertical padding

=> More informations about this toot | More toots from harshil@mastodon.social

Written by John Siracusa on 2024-12-18 at 05:15

@harshil Somehow .frame() (almost) manages it, all with a handful of variants with normal named parameters.

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by Harshil Shah :psyduck: on 2024-12-18 at 05:18

@siracusa Yeah that’s a good point!

=> More informations about this toot | More toots from harshil@mastodon.social

Written by Janko Luin :terminal: on 2024-12-18 at 06:00

@siracusa Because there are system-default values that can’t be expressed with named arguments. Ideally, most of your paddings should look something like this:

.padding()

.padding(.horizontal)

This will make your views more portable across targets. A hardcoded point value might make sense on one OS, but it won’t transfer between device classes.

=> More informations about this toot | More toots from gufo@mastodon.nu

Written by John Siracusa on 2024-12-18 at 16:41

@gufo They already support explicit point values. They just do so in a non-idiomatic way. No one is saying to remove the APIs that have implicit default values. But the ones that take explicit values should be better.

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by Janko Luin :terminal: on 2024-12-18 at 17:15

@siracusa Definitely agree. Having an EdgeInsets version but no idiomatic shorthands… that’s just madness.

=> More informations about this toot | More toots from gufo@mastodon.nu

Written by postweber on 2024-12-18 at 06:08

@siracusa I don't know Swift, but maybe the dynamic linker has trouble with old apps when a new OS supports additional named parameters.

Also the implementation is probably nicer if you can pattern match with completeness check against one parameter instead of nesting if thatParameter.

=> More informations about this toot | More toots from postweber@mstdn.social

Written by Jann on 2024-12-18 at 08:01

@siracusa you can do things like

.padding(.vertical, 20)

and especially

.padding(onlyVertical ? .veritcal : .all, 20)

=> More informations about this toot | More toots from Jann@techhub.social

Written by Mat Gadd on 2024-12-18 at 15:09

@siracusa being able to pass EdgeInsets allows for easier theming IMO, rather than needing to create your own struct and “unwrap” its properties to named parameters… but there’s no reason they couldn’t support named params and EdgeInsets, of course.

=> More informations about this toot | More toots from Drarok@mastodon.social

Written by John Siracusa on 2024-12-18 at 18:27

@Drarok Yes, that’s what I’m saying. By all means, keep the existing methods. But also make the ones that everyone expects to exist as well.

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by Martin Dufort on 2024-12-18 at 16:22

@siracusa Coming from AppKit and UIKit, that’s 1 of the reasons (and there is a huge bunch) why I hate #SwiftUWhy

=> More informations about this toot | More toots from martind@mastodon.online

Written by Matt on 2024-12-19 at 08:48

@siracusa Honestly no idea. But wonder if it’s something like:

To me

.padding(.top, 2)

Reads as “add padding to top of 2”. You choose some edges and a value.

and

.padding(top: 2)

Reads as “Set all padding. Override the default value on the top edge to 2”. You set a value for each edge. You don’t really choose an edge. .topPadding(2) might be closer? Very different default value behaviour.

So might be really confusing to have both so similar. I can see some arguments for the first.

=> More informations about this toot | More toots from Matthew@iosdev.space

Written by John Siracusa on 2024-12-19 at 11:42

@Matthew …and yet .frame() is different, despite the same reasoning making the same amount of sense there. (Which is to say, IMO, not much.)

=> More informations about this toot | More toots from siracusa@mastodon.social

Written by Neil Hargreaves on 2024-12-20 at 05:18

@siracusa feels like a lot of the knowledge encapsulated in this old WWDC video has been lost https://nonstrict.eu/wwdcindex/wwdc2010/138/

=> More informations about this toot | More toots from glotcha@mastodon.social

Written by Matt on 2024-12-21 at 21:37

@siracusa I mean this is the same language that has let vs var and one means "const". The language is dumb. Objective-C forever.

=> More informations about this toot | More toots from apple4ever@mastodon.social

Written by Nick Radcliffe on 2024-12-18 at 07:35

@siracusa #SwiftUWhy

badum-tiss

https://youtu.be/H_NG1yXT6QY

=> More informations about this toot | More toots from njr@mathstodon.xyz

Written by Dr Adam Procter on 2024-12-18 at 08:23

@siracusa hahaha excellent pun

=> More informations about this toot | More toots from adamprocter@fosstodon.org

Written by Rob Fahrni on 2024-12-22 at 15:13

@siracusa John, this is perfect for your blog! 👍🏼

=> More informations about this toot | More toots from fahrni@curmudgeon.cafe

Proxy Information
Original URL
gemini://mastogem.picasoft.net/thread/113671711870729153
Status Code
Success (20)
Meta
text/gemini
Capsule Response Time
566.48823 milliseconds
Gemini-to-HTML Time
17.592282 milliseconds

This content has been proxied by September (3851b).