My new project: Tact, a simple chat app.

Toying with Apple link previews and SwiftUI

January 07, 2022

I took a closer look at LPLinkMetadata and LPLinkView. These are part of Apple’s official SDK on all Apple platforms. They let us fetch web content metadata and use an Apple-provided UI, or draw our own UI.

I wanted to understand what kind of metadata is available, and understand the tradeoffs of using Apple’s own view, vs drawing something custom in SwiftUI. To explore all these things, I built a small SwiftUI app, available in GitHub. The app shows you metadata downloaded for a given URL, as well as how it looks with the Apple-provided UI.

LinkPreviewToy on iOS

LinkPreviewToy on macOS

SwiftUI views as function of state

Before diving into link previews, I’ll point out a SwiftUI pattern that I’ve found useful: view as function of state.

“Wait”, you say. “This is not original. This is the main point of SwiftUI. What’s the pattern and your contribution here?”

My contribution is that the other day, I started thinking of this. View as function of state. What would a pure implementation of this look like? Perhaps literally have a state variable driving the view. Since the states of a view are mutually exlusive—a view can only be in one state at any given time—an enum is a natural data type to model this.

Besides the state, views also need data, but the data is often different for each state. What’s the closest that the state and data can be to each other? They can live right in the same data type. Each value of the state enum can have a different set of associated variables, tailored for that particular state. And that can be the only thing that the view cares about: give me the state, and its associated variables.

This means that the main control flow of a view can be a switch statement. This is really neat, because it forces you to think through all the possible cases.

For regular app use, view model publishes the state as a read-only property. For something like SwiftUI previews or testing, there can be a special initializer for the view model which just takes a state and makes it the current state, without doing any other work. This means that you can very neatly make and see previews of all the possible states of your view. I think it’s quite handy.

View as function of state

Okay. On to the actual link previews.

Drilling deeper into Twitter previews

There isn’t really much to say. The code works as advertised. LPLinkMetadata gives you a bunch of metadata, which you can use to draw the UI yourself, or use the Apple-provided LPLinkView view, to get a decent UI.

Something was off with Twitter previews, though. Take a look at this example.

Preview of a tweet

The top part contains all the info that we get from LPLinkMetadata. The bottom part is the LPLinkView rendering of the same metadata. Both should, in theory, contain the same info. Yet… notice how the tweet text is there in the bottom part, and not visible in the top part.

This tells me one of two things. Either LPLinkMetadata contains more info than it publicly exposes, or LPLinkView does some extra work to fetch the missing data.

The answer is not very far. Turns out it’s the first one, and there’s more info in the metadata object than is exposed publicly. Just examine a variable of this type in the Xcode debugger to see it all.

More metadata properties

Especially the summary field looks what we’re looking for. It’s a shame there isn’t a public property for it. If anyone at Apple is reading, I’ve filed FB9836598 on this.