Apple introduced Widgets in iOS 14, which brought a new look to our phone’s home screens. Over the years, the framework has evolved to provide users with updated data. In iOS 17, Widgets become interactive, allowing users to interact with apps in innovative ways that were not possible before. By adding essential app actions to a widget, users can conveniently and engagingly interact with the app. In this tutorial, you will learn how to add interactive widgets to the Trask app using SwiftUI. If you are new to SwiftUI, widgets’ simple views are a great starting point. This tutorial covers the following topics:
1. What interactive widgets are and how they work.
2. How to create interactive widgets with a SwiftUI animation.
3. Different types of interactive widgets that you can create.
4. Best practices for designing and developing interactive widgets.
While there are no strict prerequisites, having a basic knowledge of SwiftUI and WidgetKit may be helpful. To get started, download the starter project from the provided link. Open the Trask.xcodeproj file in the Starter folder and build and run the project to see the initial screen of the Trask app. The Trask app is a general tracker app that allows users to track different tasks, things, and habits throughout the day. The app creates sample data upon launch to demonstrate the different types of tasks that can be created. The app also features a plus button to add new tasks, a swipe gesture to delete tasks, and a button at the bottom of the view to add new tasks. Before diving into interactive widgets, it’s important to familiarize yourself with some basic concepts of WidgetKit. To learn more about Widgets and how to add them, refer to the “Getting Started With Widgets” tutorial. Trask comes with a static widget that displays the status of a selectable task. To see how the widget looks, add an instance of the widget by building and running the project, minimizing the app, long-pressing on an empty area of the screen, tapping the + button, searching for Trask, and selecting the available widget. The widget code is contained in a separate Xcode target, and the app and widget need to share the same data. Trask uses a UserDefault store on an App Group container to achieve this. Widgets use a timeline to generate a series of timeline entries that render the widget at the right time. Your TaskTimelineProvider defines three methods, including the timeline(for:in:) method that returns the array of entries for a specified time. To update the timeline, you provide an update strategy. Trask uses the .never policy since the widget doesn’t need to update its view unless the user interacts with the app. Now, you are ready to add interaction to the Trask status widget. Starting with iOS 17, Apple allows two main ways of interactivity: buttons and toggles. In this tutorial, you will add a step button to the Trask status widget, allowing users to progress their favorite tasks without opening the app. Widgets’ buttons rely on a public API exposed by your app, called App Intents, to perform actions when the user interacts with the widget button. To set up the button, add the perform() method to the TaskIntent file, which is called when the intent is invoked. This method takes the selected task as input and calls a method in the store to progress the task. The UserDefaultStore is part of both the app and the widget extension, allowing you to reuse the code in both targets. Next, add the stepTask(_:) method to the TaskStore protocol and implement it in the UserDefaultStore file. This method loads all the tasks, finds the required task, calls the task’s progress() method, and saves it back in the store. Finally, add an empty stepTask(_:) method to the SampleStore to make it compliant with the new protocol definition. The TaskIntent is an intent conforming to the WidgetConfigurationIntent protocol, which allows task selection in the Edit Widget menu. The TaskStatusWidget is the actual widget, consisting of four parts: TaskTimelineProvider, TaskEntry, TaskStatusWidgetEntryView, and TaskStatusWidget. The TraskWidgetBundle declares all the extension’s widgets. The placeholder(in:) method returns sample data to render the placeholder UI while waiting for the widget to be ready. The snapshot(for:in:) method provides the data to render the widget in the gallery when choosing a widget. The timeline(for:in:) method returns the timeline entries to present at the specified time, and you can specify an update strategy, such as .never to prevent the widget from updating unless the user interacts with the app. Buttons and toggles are suitable for representing actions and binary states on widgets, respectively. On a locked device, buttons and toggles are inactive, and actions are not performed until the user unlocks the device.
Source link