Having multiple widgets with various functionalities is quite a common feature for apps nowadays. For example, a shopping app can have a widget that shows today’s promotion and another widget that shows the user’s order status.
Apple has given us 2 ways to enable our apps to support multiple widgets:
- Using a widget bundle
- Having multiple widget extensions
In this article, we will look into both of these methods individually, so let’s get started.
Note:
If you are unfamiliar with how to create a widget using WidgetKit, I highly encourage you to first read my article called “Getting Started With WidgetKit” before proceeding.
#1: Using a Widget Bundle
Let’s say we have implemented a widget named MyWidget1
.
@main
struct MyWidget1: Widget {
var body: some WidgetConfiguration {
// Widget configuration here...
// ...
// ...
}
}
Since MyWidget1
has been annotated with the @main
attribute, the system will take that as the widget extension entry point, and show the widget’s snapshot in the widget gallery.
Now, let’s say we created another widget named MyWidget2
in the same widget extension. If we try to mark MyWidget2
with the @main
attribute, we will get a compile error saying:
'main' attribute can only apply to one type in a module
This error basically means that we cannot have 2 entry points in the same widget extension. So what should we do so that MyWidget1
and MyWidget2
can both appear in the widget gallery? This is where the Widget Bundle comes in.
Here’s how to use a widget bundle:
@main
struct MyWidgetBundle: WidgetBundle {
@WidgetBundleBuilder
var body: some Widget {
MyWidget1()
MyWidget2()
}
}
As you can see, the way to use a widget bundle is pretty straightforward. All we need to do is to annotate it with the @main
attribute and make both MyWidget1
and MyWidget2
as part of its body. Be sure to remove the @main
annotation at MyWidget1
too.
Notice that the widget gallery will display the widgets based on the ordering of the widgets in the widget bundle’s body.
Breaking the Widget Bundle Limitation
Now that we have learned how to use a widget bundle, does it mean we can now add as many widgets as we want into the widget bundle’s body? Unfortunately, that’s not the case.
If we try to add more than 10 widgets to the widget bundle’s body, we will get a compile error “Extra argument in call“.
@main
struct MyWidgetBundle: WidgetBundle {
@WidgetBundleBuilder
var body: some Widget {
MyWidget1()
MyWidget2()
MyWidget3()
MyWidget4()
MyWidget5()
MyWidget6()
MyWidget7()
MyWidget8()
MyWidget9()
MyWidget10()
MyWidget11() // 🔴 Error: Extra argument in call
}
}
To overcome such a limitation, all we need to do is to create another widget bundle and add its body to the first widget bundle’s body.
@main
struct MyWidgetBundle: WidgetBundle {
@WidgetBundleBuilder
var body: some Widget {
MyWidget1()
MyWidget2()
MyWidget3()
MyWidget4()
MyWidget5()
MyWidget6()
MyWidget7()
MyWidget8()
MyWidget9()
AnotherWidgetBundle().body
}
}
struct AnotherWidgetBundle: WidgetBundle {
@WidgetBundleBuilder
var body: some Widget {
MyWidget10()
MyWidget11()
}
}
Theoretically, this should enable us to support an unlimited number of widgets on Xcode. However, I am not sure whether there is a limitation on the number of widgets allowed in the widget gallery, if you know the answer, please let me know.
#2: Having Multiple Widget Extensions
Aside from using widget bundles, another way of supporting multiple widgets is to have multiple widget extensions. According to Apple, such a way should only be used in a very specific situation.
Let’s say we have an app with multiple widgets and only some of them require the location service. In this case, we can separate these widgets into multiple extensions. This allows the system to only prompt the user for the widgets that use the location service.
You can learn more about how to add a widget extension here.
There you have it! That’s how you can make your app support multiple widgets. If you like this article, you might want to check out my other articles related to WidgetKit.
Feel free to follow me on Twitter and subscribe to my newsletter so that you won’t miss out on any of my upcoming iOS development-related articles.
Thanks for reading. 👨🏻💻
👋🏻 Hey!
While you’re still here, why not check out some of my favorite Mac tools on Setapp? They will definitely help improve your day-to-day productivity. Additionally, doing so will also help support my work.
- ✨ Bartender: Superpower your menu bar and take full control over your menu bar items.
- ✨ CleanShot X: The best screen capture app I’ve ever used.
- ✨ PixelSnap: Measure on-screen elements with ease and precision.
- ✨ iStat Menus: Track CPU, GPU, sensors, and more, all in one convenient tool.