✅ Bringing App Intents to Your SwiftUI App 🍭

January 13, 2025
Sponsored

Tuist - Scale your Swift App development

We are an integrated and open core toolchain that extends Apple's official tools with insights, optimizations, and workflows to help you build better apps faster.

Welcome to issue #28 of the iOS Coffee Break Newsletter 📬 and the first edition of 2025. I hope you had a lovely start of the year 🥳!

This week I wrote an article that discusses the advantages and implementation details of the App Intents and the App Shortcuts frameworks in iOS, using a To-dos sample application as a working example to demonstrate how they can make user interactions easier and more intuitive.

The App Intents framework enables seamless integration of your app's features with system experiences like Siri, Spotlight and Shortcuts. Enhanced by Apple Intelligence, it boosts discoverability and personalization by suggesting actions and enabling interactions across apps.

For this example, we are interested in the following actions:

  • Show the list of tasks
  • Add a new task
  • Remove a task
  • Mark a task as completed

Defining App Intents

To define App Intents, just add a new file to your main app target and create a struct that conforms to the AppIntent protocol. The system will automatically discover any intents defined by your app and will show them accordingly where appropriate.

We will take as example the add to-do intent that looks as follows:

import AppIntents
 
/// Add to-do App Intent
struct AddTodoIntent: AppIntent {
    static var title: LocalizedStringResource = LocalizedStringResource(stringLiteral: "Add item to todos list")
    static var description: IntentDescription? = IntentDescription(stringLiteral: "Add an item to todos list")
 
    @Parameter(title: "Todo title")
    var todoTitle: String?
 
    func perform() async throws -> some ProvidesDialog {
        guard let todoTitle else {
            let dialog = IntentDialog("What todo item you would like to add?")
            throw $todoTitle.needsValueError(dialog)
        }
 
        let newTodo = Todo(title: todoTitle)
        do {
            try await insert(todo: newTodo)
            let dialog = IntentDialog("'\(todoTitle)' was added to your todos list.")
            return .result(dialog: dialog)
        } catch {
            throw error
        }
    }
 
    @MainActor
    func insert(todo: Todo) async throws {
        let todosManager = TodosManager(context: MyTodosApp.container.mainContext)
        try await todosManager.insert(todo: todo)
    }
}

Making your Intents accessible through Shortcuts

A great feature of Intents is their ability to appear in multiple system locations. To ensure actions are accessible via Spotlight, you need to implement an AppShortcutsProvider instance.

import AppIntents
 
struct MyTodosShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: AddTodoIntent(),
            phrases: [
                "Add an item to \(.applicationName)",
                "Add item to \(.applicationName)",
            ],
            shortTitle: LocalizedStringResource(stringLiteral: "Add an item to todos list"),
            systemImageName: "plus.circle.fill"
        )
    }
}

With this setup, your app's functionality becomes fully accessible as a Shortcut.

Here is a demo of the sample to-dos application using App Intents.

App Intents can also power interactive widgets, controls and live activities, which I plan to explore in future issues!

To explore the full implementation of the sample application and to get more details of how App Intents and App Shortcuts frameworks work, visit my latest article on my blog.

Now it is time to dive into some iOS development topics submitted by the community. Here are this week's highlighted resources. Hope you enjoy 🙌.

CURATED FROM THE COMMUNITY

🪚 Creating tiny utility apps with SwiftUI Previews

In this post, Daniel demonstrates how to create lightweight apps without needing to install them on a device by leveraging SwiftUI Previews and Swift Package internal views. Thanks to SwiftUI, which simplifies development compared to UIKit and AppKit, you can build cross-platform apps efficiently.

Personally, I believe this method serves as an excellent alternative to standalone apps, streamlining the development process and saving time to focus on other priorities 👌.

🪥 How a new Xcode 16 feature helped my work project eliminate 66,000 lines of code

Xcode 16's new buildable folders don't depend on .pbxproj for recognising files, which helps teams avoid possible merge conflicts with file changes in their git branches. This feature allowed Makwan's team to find over 100 unused Swift files and eliminate a total of 66,000 lines of code.

I suggest reading this article for a deeper understanding of how the author and the team tackled this time-consumig process. It might inspire you to clean up some of your project's files as well!

🪝 Swift 6: Typed Throws

Swift 6 introduces many exciting features, including Typed Throws, which improve the way we handle errors.

In her latest blog post, Vera explains how specifying error types allows the compiler to detect issues more appropriately.

🖊️ The ultimate guide to signing CLIs for macOS (Darwin)

Did you ever get the error "'your-cli' can't be opened because Apple cannot check it for malicious software." after installing a macOS CLI tool? I bet you did - this happens because macOS has a security feature called Gatekeeper, which is designed to ensure that only trusted software runs on the system.

Pedro from Tuist has written a comprehensive guide on signing and notarizing your CLI tool for macOS to resolve this issue effectively!