Categories
iOS SwiftUI

iOS 13 Rich Link Previews With SwiftUI

Apple gave major emphasis to modernizing the UI during WWDC 2019. Be it through path-breaking changes like SwiftUI or the subtler ones like the new LinkPresentation framework.

The LinkPresentation framework allows developers to integrate visually rich looking preview links in their applications starting iOS 13, something that could earlier be seen in Apple’s Messaging app.

Despite not having had the same limelight as a few other releases this year, LinkPresentation can play a key role in enhancing the user experience of your applications.

Our Goal

  • Discussing the workings of LinkPresentation.
  • Integrating rich links in our Swift UI-based iOS application.

LinkPresentation Framework

The newly introduced framework allows you to embed content-based URL previews in your application, which stays consistent across the OS.

Largely, the LinkPresentation framework consists of the following:

  • LPMetaDataProvider — This class is used to fetch the metadata from a URL.
  • LPLinkMetaData — Acts as the container for the metadata. It is responsible for storing the content, icon, images, and videos of the rich link. Optionally, you can set your own custom data in this class as well.
  • LPLinkView — This provides the visually rich looking preview of our link with embedded content and images.
  • LPError — Typically, this deals with the error handling part of the LinkPresentation framework.

Under the hood, the LinkPresentation framework uses the WKWebView to fetch the metadata.

The following code snippet showcases an example of fetching the metadata and displaying it in a LinkView:

import LinkPresentation

let metadataProvider = LPMetadataProvider()
let url = URL(string: "https://medium.com/@anupamchugh/")!

metadataProvider.startFetchingMetadata(for: url) { [weak self] metadata, error in
    guard let metadata = metadata else { return }

    let linkView = LPLinkView(metadata: metadata)
    self?.view.addSubview(linkView)
}

For cases where the metadata cannot be retrieved for some reason, we can set our own custom title, icon, video, or URLs as placeholders:

let md = LPLinkMetadata()
md.title = "Custom title"
md.url = url
md.imageProvider = ....
let linkView = LPLinkView(metadata: metadata)

In the next section, we’ll be developing a SwiftUI-based iOS application that displays a list of rich link previews. Let’s get started.

Create a UIView

Yes! We’ll be conforming to the UIViewRepresentable to wrap our UIKit view inside a SwiftUI view.

struct LinkRow : UIViewRepresentable {

    var previewURL:URL

@Binding var redraw: Bool

    func makeUIView(context: Context) -> LPLinkView {
        let view = LPLinkView(url: previewURL)

        let provider = LPMetadataProvider()
        provider.startFetchingMetadata(for: previewURL) { (metadata, error) in
            if let md = metadata {
                DispatchQueue.main.async {
                    view.metadata = md
                    view.sizeToFit()
                    self.redraw.toggle()
                }
            }
            else if error != nil
            {
                let md = LPLinkMetadata()
                md.title = "Custom title"
                view.metadata = md
                view.sizeToFit()
                self.redraw.toggle()
            }
        }

        return view
    }

    func updateUIView(_ view: LPLinkView, context: Context) {
        // New instance for each update
    }
}

In the above code, there’s a redraw binding instance. It notifies the SwiftUI view to redraw the rich link preview once the metadata is fetched.

sizeToFit() is used for automatic cell sizing to fit the rich link previews.

Creating Our Data Structure

Next, we create a structure that conforms to the Identifiable protocol for the SwiftUI list to identify each row by its unique identifier.

struct StringLink : Identifiable{
var id = UUID()
var string : String
}

We’ll populate our array of StringLink with URL strings in the ContentView in the next section.

Build the ContentView

Finally, we pass our data to the SwiftUI List which holds the UIView LinkRow as shown below:

import LinkPresentation
struct ContentView: View {

@State var redrawPreview = false    
    let links : [StringLink]  = [] //add your url links here
    var body: some View {
        List(links){ l in
            LinkRow(previewURL: URL(string: l.string)!, redraw: self.$redrawPreview)
        }
        .environment(\.defaultMinListRowHeight, 200)

    }
}

We can set the default height and width of the lists using the environment property as we did above.

In return, we get the following outcome in our SwiftUI live preview.

ios13-rich-link-previews

There’s More

The LinkPresentation framework can be used for optimizing share sheets by prefetching the metadata of the URL links, thereby removing the latency when the share sheet pops up.

You can even cache the metadata of the URLs to prevent reaching out to the server every time for the same link.

That wraps up this piece. I hope you enjoyed reading it.

By Anupam Chugh

iOS Developer exploring the depths of ML and AR on Mobile.
Loves writing about thoughts, technology, and code.

Leave a Reply

Your email address will not be published. Required fields are marked *