App Clips: A first glance at the new way to access an iOS app

During WWDC20 Apple is introducing new App Clips feature. As it's described in the landing page:

An app clip is a small part of your app that’s discoverable at the moment it’s needed.

Apple already suggested some possible use cases such as ordering from a take-out restaurant or renting a scooter. And App Clips will be discovered and invoked by using new App Clip Codes, NFC Tags, QR Codes, Messages, or as place cards in Maps.

It looks like a great move forward in reducing friction and getting an app into users' hands as fast as possible.

We'll take a look at the initial steps of how these App Clips could be implemented and introduced in the project.

Prerequisites

Xcode 12 or higher.

Getting Started

We start by creating a new project and selecting the creation of a new target.

App Clip New Target

We select a new App Clip target and add it to our application.

App Clip New Target

Add Associated Domain

We need to provide an associated domain for both App and App Clip targets. If App is not installed the link will open App Clip. Otherwise full App will be opened instead.

We do it by selecting Target -> Signing & Capabilities, clicking + sign, and choosing Associated Domains.

Creating Associated Domain

Next, we enter our associated domain value which must follow pattern of appclips:domain. In this instance, we can enter appclips:example.com.

Associated Domains Example

Running App Clip target

App Clip target can be run and debugged just like an App target.

We can open ContentView.swift inside an App Clip target, make changes, and run.

struct ContentView: View {
    var body: some View {
        Text("Hello, App Clip!").padding()
    }
}
Hello App Clip Simulator Screen

Configuring App Clip

App Clip is invoked via URL which can contain context-related information and be used in the configuration.

Let's say we want to provide a user with a more personalized greeting message after App Clip was invoked. We can pass binding name variable to ContentView.

struct ContentView: View {
    @Binding var name: String

    var body: some View {
        Text("Hello, \(name)").padding()
    }
}

This example uses a new App lifecycle in SwiftUI which enables entire apps to be written completely in SwiftUI.

Information about invocation is passed through lifecycle events. We can use onContinueUserActivity to be notified about App Clip being launched with parameters.

More information about using legacy lifecycles can be found on Access the Invocation URL section.

After that, we take the incoming URL and its first path component. Now first path parameter passed through URL will be set as a name.

@main
struct AppClipSneakPeekClipApp: App {
    @State var name = ""

    var body: some Scene {
        WindowGroup {
            ContentView(name: $name).onContinueUserActivity(NSUserActivityTypeBrowsingWeb, perform: respondTo)
        }
    }

    func respondTo(_ activity: NSUserActivity?) {
        guard let name = firstParameterValue(from: activity) else { return }

        self.name = name
    }

    private func firstParameterValue(from activity: NSUserActivity?) -> String? {
        // Parsing components from URL
        guard let activity = activity else { return nil }
        guard let incomingURL = activity.webpageURL else { return nil }
        guard let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true) else { return nil }

        // Taking first parameter: example.com/?parameter=Lisa
        return components.queryItems?.first?.value
    }
}

Testing

Launching AppClip target now does not show any name value. It makes sense as we didn't pass any URL with parameters to our app.

We can automatically test it by providing Environment Variable for App Clip scheme. It can be done by selecting App Clip scheme -> Edit Scheme -> Run and set the value of _XCAppClipURL of test URL value. We set it to https://example.com/?parameter=Lisa to have a first parameter value.

Adding Environment Variable

If we launch the application now, the value is received through lifecycle event and updated inside a view.

iOS Simulator with result

What about App Clip Card?

App Clip Card itself that is shown with a suggestion to open an App Card is not developed through Xcode. The information displayed in this card can be configured through App Store Connect. Developers will be able to change a header image, subtitle, and title on the action button.

Where do we go from here?

App Clip looks like a promising addition to the ecosystem and it will be interesting to see how it will be used and adopted by both developers and users.

The example project can be found on GitHub.

Apple provides a lot of helpful resources for going more in-depth into App Clips.