Jacob’s Tech Tavern

Jacob’s Tech Tavern

Share this post

Jacob’s Tech Tavern
Jacob’s Tech Tavern
Secret SwiftUI: A practical use for _VariadicView
Copy link
Facebook
Email
Notes
More
User's avatar
Discover more from Jacob’s Tech Tavern
Every week, I'll send you ludicrously in-depth articles about SwiftUI performance, advanced Swift concurrency, and under-the-hood iOS internals.
Over 5,000 subscribers
Already have an account? Sign in

Secret SwiftUI: A practical use for _VariadicView

I finally found a use case for this private API

Jacob Bartlett's avatar
Jacob Bartlett
Feb 10, 2025
22

Share this post

Jacob’s Tech Tavern
Jacob’s Tech Tavern
Secret SwiftUI: A practical use for _VariadicView
Copy link
Facebook
Email
Notes
More
5
2
Share

Inspiration struck. I finally realised a practical use case for _VariadicView: a reusable ChatList component that automatically applies scroll inversion on the contents.


Subscribe to Jacob’s Tech Tavern for free to get ludicrously in-depth articles on iOS, Swift, tech, & indie projects in your inbox every week.

Full subscribers unlock Quick Hacks, my advanced tips series, and enjoy my long-form articles 3 weeks before anyone else.

I’m kind of late to the party on this, frankly.

_VariadicView helps us create custom VStacks. Our own flexible tab bars. Bespoke pickers and lists. I started writing this article in March 2024, but was stumped trying to find a non-contrived example—one that would actually be useful in production.

While mulling it over on a mental background thread, this article faded into a dusty backlog alongside aborted magnum opi such as Through The Ages: Apple Concurrency APIs and Dumb Ways To Maximise Your App Binary Size.

Recently, that all changed.

At midnight, I was doing what we all do once our wives fall asleep: reading Vincent Pradeilles. Specifically, his article on building inverted scroll for messaging apps.

Inspiration struck. I finally realised a practical use case for _VariadicView: a reusable ChatList component that automatically applies scroll inversion on the contents.

Today, much like our scrolling, let’s work backwards.

We’ll implement a scroll inversion, and experience the pain point together as our UI grows more complicated. Only then will I introduce _VariadicView, take you under the covers to explain how it all works, then demonstrate how you can use _VariadicView to address this specific pain point in your own apps.

Building an Inverted Scroll

Inverted chat scroll is the cornerstone of messaging app UX. It’s just a scroll view that starts at the bottom (with the newest messages), so the user scrolls up to see older content.

This differs from the standard scrolling feed UX, where you start at the top of the screen and scroll down for more content.

The trick to implementing this is deceptively simple: you flip the scroll view so it’s upside down. This can be done with 2 lines of SwiftUI modifiers:

.rotationEffect(.radians(Double.pi))
.scaleEffect(x: -1, y: 1, anchor: .center)

Applied to a List view, this gives us the “start at the bottom and scroll up” effect we want, however the chat message content is also inverted!

To fix this, we have to apply the same vertical inversion individually to all the pieces of content. This leaves your view looking a little like this:

struct ChatList: View {
    var body: some View {
        List {
            ForEach(message) { 
                MessageView(message: $0)
                    .inverted()
            }
        }
        .inverted()
    }
}

This does the job, but becomes unwieldy and error-prone as you bring your chat app up to parity with iMessage.

As more types of view are implemented like messages, date headers, and text fields, this gets messy fast.

List {
    TextField() 
        .inverted() 

    TextEntrySeparator() 
        .inverted()

    ForEach(message) {
        if message.isDateHeader { 
            MessageDateHeader()
                .inverted()
        }
           
        MessageView(message: $0)
            .inverted()
    }
}
.inverted()

Enter: _VariadicView.

WTF is a _VariadicView?

_VariadicView is a private-ish SwiftUI API, and the underlying implementation detail for many of the container views you use every day.

It sounds pretty obscure, however its naming is actually pretty straightforward: it’s a view that can be passed any number of views, hence variadic.

_VariadicView lets you do one thing well:

  • Create reusable container components

  • …that can handle multiple types of child view passed in

  • …to which you can apply similar sets of modifiers.

Despite being an underscored “private” API, it’s safe to use in production—many @frozen SwiftUI APIs explicitly conform to the protocol. You won’t have to worry about app review when using it—the API is already emitted into your code implicitly whenever you use a SwiftUI container view like HStack.

How to use _VariadicView

We want to set up a simple container for all our chat content that handles the inversion automatically. We want to implement this once, then apply the inverted scrolling for free anytime we like.

_VariadicView.Tree

We start by creating this container view: ChatList.

struct ChatList<Content: View>: View {
    
    var content: Content

    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }
    
    var body: some View {
        _VariadicView.Tree(ChatLayout()) {
            content
        }
    }
}

We initialise this view with content—the child views, such as messages, passed into the ChatList container.

The body declares a _VariadicView.Tree. This represents a SwiftUI view tree which can be rendered by the layout engine. The API declaration looks like this:

public enum _VariadicView {
    public struct Tree<Root, Content> where Root : _VariadicView_Root 
}

We pass in a Layout that conforms to _VariadicView_MultiViewRoot and content—the child views passed into our container.

_VariadicView_MultiViewRoot

Now, we can implement this Layout. This is where the magic happens.

struct ChatLayout: _VariadicView_MultiViewRoot {
    
    func body(children: _VariadicView.Children) -> some View {
        List {
            ForEach(children) { child in
                child
                    .inverted()
                    .listRowSeparator(.hidden)
            }
        }
        .listStyle(.plain)
        .inverted()
    }
}

The body of a _VariadicView_MultiViewRoot is the root of the SwiftUI view tree hierarchy. It lays out the child views that represent the leaf nodes in this view hierarchy.

This gives us a new power not present in vanilla SwiftUI code: we can declare a container view with child views, and perform modifications to, or between, each child view without the parent knowing.

In short:

The power of _VariadicView is the ability to do stuff between the root and the leaf nodes of a container view.

This means our container can wrap functionality like inverting a scroll, and re-inverting each child view individually. Instead of leaking this complexity into the top-level view every time we touch the list, this inversion becomes an implementation detail—we can hide this complexity in the container. The devs adding new chat functionality or polishing the UI may never know about it.

_VariadicView.Children

Inside the body, we have some pretty standard SwiftUI code to represent a scrolling list, set basic styling, and vertically invert all the content.

_VariadicView.Children represents the content in our ChatList—the child views passed into our container. This conforms to RandomAccessCollection, Identifiable, and View. This means we can iterate through and render each child, even subscripting them if we want further individual customisation.

Putting It All Together

Now that we’ve created our ChatList container, let’s see it in action.

NavigationView {
    ChatList {
        TextField("Reply", text: $reply)
        
        ForEach(messages) {
            ChatMessageView(message: $0)
        }
    }
    .navigationTitle("Chat")
}

ChatList internally handles the UI inversion, so we can focus fully on building a sick messaging app for our users!

Despite being the best example I could find in 11 months, this approach isn’t limited to Chat UIs. Any dynamic container, carousel, or list can apply _VariadicView to create flexible components to delight your colleagues and end-users.

If you’re still confused about _VariadicView, that’s because it’s confusing. The key takeaway is that _VariadicView allows you to do create containers that do stuff between their root and leaf nodes.

In practical, concrete, non-jargony terms, _VariadicView is occasionally quite useful when you want to wrap some annoying domain-specific boilerplate in a component.

If you want to check out the whole project, goto _Secret_SwiftUI on Github.

The open-source project also includes _trait to create a custom Tab Bar. _trait is another private SwiftUI API that allows you to associate any type of metadata to a view, which can then be queried within the container. This data ostensibly communicates up the view tree during the initial layout pass, making _traits more performant than preference keys.

I didn't write much about it here, because I still haven’t thought of a good use case. Vincent, if you can think of one, consider it a free idea!

Thanks for reading Jacob’s Tech Tavern! 🍺

Jacob’s Tech Tavern
Dad doing iOS @ London Startups. Every week, I'll send you ludicrously in-depth articles about iOS, Swift, tech, & indie projects.
By Jacob Bartlett

Subscribe to Jacob’s Tech Tavern

By Jacob Bartlett · Hundreds of paid subscribers
Every week, I'll send you ludicrously in-depth articles about SwiftUI performance, advanced Swift concurrency, and under-the-hood iOS internals.
Özgün Doğuş Can's avatar
Alex Merz's avatar
Eldhose Lomy's avatar
Lucas Derraugh's avatar
Cameron Cooke's avatar
22 Likes∙
2 Restacks
22

Share this post

Jacob’s Tech Tavern
Jacob’s Tech Tavern
Secret SwiftUI: A practical use for _VariadicView
Copy link
Facebook
Email
Notes
More
5
2
Share

Discussion about this post

User's avatar
Alex Simpson's avatar
Alex Simpson
Feb 11

Your link to the Github repo at the end doesn't seem to be working!

Expand full comment
Like (1)
Reply
Share
1 reply by Jacob Bartlett
Lucas Derraugh's avatar
Lucas Derraugh
Feb 11

Nice use case and one I may adopt 😅

Expand full comment
Like (1)
Reply
Share
1 reply by Jacob Bartlett
3 more comments...
My Toddler Loves Planes, So I Built Her A Radar
An adorable side project featuring SwiftUI, MapKit, and open-source APIs
Nov 27, 2023 • 
Jacob Bartlett
85

Share this post

Jacob’s Tech Tavern
Jacob’s Tech Tavern
My Toddler Loves Planes, So I Built Her A Radar
Copy link
Facebook
Email
Notes
More
48
Apple is Killing Swift
A great language strangled by governance
Oct 21, 2024 • 
Jacob Bartlett
122

Share this post

Jacob’s Tech Tavern
Jacob’s Tech Tavern
Apple is Killing Swift
Copy link
Facebook
Email
Notes
More
8
Impress at Job Interviews by Inspecting their App Bundle
Techniques Apple doesn’t want you to know
Aug 19, 2024 • 
Jacob Bartlett
37

Share this post

Jacob’s Tech Tavern
Jacob’s Tech Tavern
Impress at Job Interviews by Inspecting their App Bundle
Copy link
Facebook
Email
Notes
More
6

Ready for more?

© 2025 Jacob Bartlett
Privacy ∙ Terms ∙ Collection notice
Start writingGet the app
Substack is the home for great culture

Share

Copy link
Facebook
Email
Notes
More

Create your profile

User's avatar

Only paid subscribers can comment on this post

Already a paid subscriber? Sign in

Check your email

For your security, we need to re-authenticate you.

Click the link we sent to , or click here to sign in.