iOS 13 Rich Link Previews With SwiftUI
Introducing the new LinkPresentation framework
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 UIViewLinkRow
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.
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.