Screen vs View in SwiftUI


4 min read

When SwiftUI was announced in June 2019, I was on a team that decided we were going to use SwiftUI to build our new large-scale production app. We started right away and rode the wild roller coaster of the SwiftUI beta rush of Summer 2019, and we were loving it! Kudos to the SwiftUI team for working so feverishly that Summer! ๐Ÿซถ๐Ÿผ

As we continued to build, the number of SwiftUI files naturally grew in our new project and it became increasingly difficult to tell whether a SwiftUI file name corresponded to the actual full layout of a screen or to a single custom view or component we had created. Because every single SwiftUI file we created ended in View.swift, and there were a lot of files! After all, literally no one in the world had ever built a large-scale Production app in this new "SwiftUI" framework, so we were forging our own path coming up with our own naming conventions. (I mean, "View" isn't anything novel, but hopefully you get what I mean.)

Then suddenly, a seemingly simple naming solution dawned on me: if you're creating a new SwiftUI file whose layout is intended to represent an entire screen, then use the Screen suffix, e.g. SettingsScreen.swift; otherwise, use the View suffix, e.g. BasicRowView.swift. And boom! Just like thatโ€”the moment we started using this naming convention, the struggle to distinguish between subview files and full-screen layout files vanished!

Fast forward almost 5 years (2024), I'm still working full-time using SwiftUI, and I still follow the exact same naming convention. But something has changed. In those early days, we were extraction-happy: we extracted subviews out into their own files all over the place. And that's how we ended up with a lot of files. I'm not saying that's a bad thing though. The thing that has changed/evolved since then is my approach to view extraction. These days, the vast majority of my SwiftUI files are Screen files, with only someView files. Because I've become much more selective about what I extract out into its own View file. I'll explain.

Let's say your app has several screens that each list things out, and every screen uses the exact same UI for the rows. In this situation, since the row layout is used in more than one screen in the app, I would extract the row UI (which I would consider a "subview" of a "screen") into its own file using the View suffix, e.g. PrimaryRowView.swift and I would use it throughout the app. On the flip side, you might have a screen that uses a unique style for its rows and that particular screen is the only screen in the app that uses that unique style of row. Well, since that row style is only used in one single screen in the app, I would opt to create the row layout directly within the Screen file itself using a func (and/or computed property) returning some View like this:

private func cardRowView(title: String) -> some View {
Notice how I used the "View" suffix in the func name since I consider this is a "subview" of the "screen" that it lives in.

If, at any point in time, that unique style ends up being used in more that one screen, then it's a pretty light lift to bust it out into its own file as a reusable component. No big deal.

It may be worth mentioning, some say breaking up complex views into smaller pieces that live in their own files may improve performance. I haven't measured this sort of thing myself, and my article today isn't about performance. Full stop ๐Ÿ˜…

So, hey, you've read an article about a naming convention. And it probably won't change the world. But it might change your world by making your code vastly easier to reason about. And if your code is easier to reason about, it'll be that much easier for you to change the world. ...what? Go to sleep.

That was way too serious.
kloveyoubye ๐Ÿ‘‹๐Ÿผ

P.S. Do you remember what it was like Googling something about SwiftUI in Summer 2019 and having it return 0 results? ๐Ÿ˜…

Did you find this article valuable?

Support Scott Smith by becoming a sponsor. Any amount is appreciated!