Build Your First iOS Widget — Part 1

Creating an emoji app and widget with SwiftUI

Ale Patrón
Jul 16 · 8 min read

Note: This is part 1 of a 3-part tutorial. Find part 2 here, and part 3 here.

Image for post
Image for post
Small iOS 🦄 emoji widget.

During WWDC 2020, Apple announced the introduction of app widgets for iOS (as well as iPadOS and MacOS). With the new WidgetKit framework, you can build widgets that can be added to your home screen to let you see important information at a glance. While you may be familiar with widgets in other operating systems, they are a completely new addition to iOS, and developers are already starting to build very exciting widgets using WidgetKit.

So let’s go ahead and build a new widget. We’re going to create a simple app I like to call Emojibook; this app will display a list of emoji along with their names, as well as more details about the emoji whenever one of them is tapped. We will create a widget that you can add to your homescreen to display an emoji, which will be updated randomly every hour or so.

Note: You’ll need Xcode 12 Beta 2 or higher to follow this tutorial.

This is what our app will look like:

Image for post
Image for post
Emojibook app and widget.

Let’s start by building our simple list-based app. Open up Xcode and create a new iOS App project called Emojibook; make sure SwiftUI is selected in the Interface options and SwiftUI App is selected in the Life Cycle options.

Image for post
Image for post
Creating the Emojibook project.

Most of our code will be in ContentView.swift, which we will rename to have a more descriptive name. Change the name of this file to EmojibookListView.swift, and rename the ContentView struct to EmojibookListView, making sure to update its usage wherever it’s necessary (see my Xcode tricks article to learn how to do this with one click).

In the body section of EmojibookListView we will add the content of our app. We will embed the content in a NavigationView, and inside it we will add a List, inside our List we will add the emoji.

If you run your app, it will look something like this:

Image for post
Image for post

It looks good, but we want to display a different emoji on each row along with its name, not a number. To do this, we will first add an EmojiDetails struct that will include the emoji itself, its name, and its description (we will use this description later on). Create a new file called EmojiDetails and add the following code:

The Identifiable extension is necessary to be able to identify each EmojiDetails element when we add them to our list with the ForEach struct. Since we will display different emoji, the emoji string itself can be used as the id.

Now we need to create a list of EmojiDetails to be displayed in our app. Let’s create another file called EmojiProvider, here we will add any methods needed to get the emoji data for our app. I’ve gone ahead and created a list that includes 26 distinct emoji, you can always modify it to include any emoji you want.

Emoji data provider, descriptions provided by

In our EmojibookListView file let’s add a reusable view called EmojiItemView that will be used for each row of our List.

Now we can use our EmojiProvider to get the list of all EmojiDetails, and modify the ForEach section of our List like so:

Let’s run our app again and see how it looks.

Image for post
Image for post

Nice! Now let’s add a view to display an emoji’s description.

To show all details about an emoji, we will use SwiftUI’s sheet component. Our sheet will look like this:

Image for post
Image for post
Emoji details view.

Let’s first add a reusable view called EmojiDetailsView that will display emoji details and will be used as the sheet’s content, similar to the EmojiItemView we added before.

To display the sheet, we will need to add a boolean binding to determine whether the sheet should be visible. We will also need to handle taps on items in our List, and show the EmojiDetailsView whenever a tap on an item is detected.

To handle taps on an EmojiItemView we should first embed it in a Button, whose action will be to toggle the showingDetail boolean, and whose label will be the EmojiItemView. Next we can add our sheet, bound to the showingDetail boolean, and whose content is an EmojiDetailsView showing details of the tapped emoji.

Now if you run your app, you should be able to tap on any emoji item and see its details:

Image for post
Image for post
Emoji details sheet.

Cool, we can finally start working on our widget!

Now that our simple app is done, we can finally add our emoji widget. To get started, we first need to add a Widget Extension target to our app. To do this open the File menu, select New and then select Target.

Image for post
Image for post
Adding a Target to our app.

Once the menu opens up, search for ‘Widget’ and select Widget Extension. Press Next, name your widget ‘Emojibook Widget’, and make sure the Include Configuration Intent option is not selected. Press Finish and activate the widget extension scheme when prompted.

Image for post
Image for post
Adding a Widget Extension.

On the Project Navigator you can now see that Xcode created the Emojibook Widget folder. Go ahead and open the Emojibook_Widget.swift file. This file includes the skeleton code required to build a widget.

One important thing to know is that the data of your widget will be provided through a TimelineEntry, which can be updated based on your app’s use case. For example, a stock market widget that displays stock prices will probably update very frequently throughout the day.

The first thing you should see in Emojibook_Widget.swift is a TimelineProvider. The snapshot method is used to quickly provide a TimelineEntry to present a widget view that is used in transient situations, for example, in the widget gallery.

Image for post
Image for post
Widget gallery.

Then you should see the timeline method. Through this method, you can provide an array of timeline entries, one for the present time, and others for future times based on your widget’s update interval. We will be updating our widget with a new emoji every hour, so our timeline entries will be an hour apart from each other.

Below that is the code that defines our TimelineEntry, which we will be updating later. Then we have a PlaceholderView struct used by iOS to display our widget on the lock screen and before rendering the widget’s content. Next is the Emojibook_WidgetEntryView defining the visual interface of our widget. Finally we see the Emojibook_Widget struct marked with the @main annotation, this means that this is where the entry point of our widget is. Here we provide a WidgetConfiguration, basically everything the operating system needs to know to display our widget: what the timeline is, how the placeholder view should look, how the actual widget should look, and our widget’s name and description.

Let’s first start by making sure we can use EmojiDetails and EmojiProvider in our widget by adding them to our WidgetExtension target. We can do this by selecting the file, and opening the inspector, then selecting the widget target:

Image for post
Image for post

Now we can define the UI of our widget. To better organize our code, we will be putting this in a separate swift file. So go ahead and create a new swift file and name it EmojiWidgetView.swift, making sure it’s added as part of the Emojibook WidgetExtension target.

Image for post
Image for post
Creating the widget view.

Let’s add the content of our widget, like so:

We can now go back to Emojibook_Widget.swift and use the view we just defined to display our widget. But before we do this, let’s add a new method in our EmojiProvider that will give us a random EmojiDetails object from our list of emoji. We will use this method to get a random emoji to display in our widget.

We can now modify our TimelineEntry so that it includes an instance of EmojiDetails.

We will have to update our code so that we provide an EmojiDetails instance wherever we create a TimelineEntry–this should include the snapshot method, the timeline method, and the PreviewProvider if you’re using live previews. This is also where we will use our EmojiProvider.random() method.

SimpleEntry(date: entryDate, emojiDetails: EmojiProvider.random())

Now, in Emojibook_WidgetEntryView, we will replace the default Text component and use our EmojiWidgetView, getting the EmojiDetails from the entry.

Finally, let’s update our widget’s name and description. We can do this by updating the StaticConfiguration under Emojibook_Widget. We will only support small widgets for now, so let’s update our configuration to reflect this by adding the supportedFamilies modifier as well.

To test our widget in the simulator we should first set our active scheme to be the Emojibook WidgetExtension.

Image for post
Image for post
Testing the emoji widget.

Now run your app, you should be able to see the widget in the simulator, and pressing it will open the Emojibook app.

Image for post
Image for post
Random emoji widget.

Thanks for reading! I hope you enjoyed this article and found it useful. You can find the completed part 1 app on GitHub. Part 2 is available here; you can find part 3 here.

Next up: In part 2 of this tutorial, I will show you how to support different widget sizes and adjust the widget’s content based on its size, as well as how to create deep links that open a specific view of your app when tapping on the widget. In part 3, I will show you how to use SiriKit intents to make user-configurable widgets.

To learn more about WidgetKit, make sure to use Apple’s awesome resources:

The Startup

Medium's largest active publication, followed by +719K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store