Advanced Concepts
Developing Widgets for iOS
Widgets display content and offer specific functionality without requiring people to open your app. People can use widgets to organize and personalize their devices, quickly accessing the information and features they need.
A widget elevates and displays a small amount of timely, relevant information from your app or game so people can see it at a glance in additional contexts.
Starting with NativeScript 8.9 CLI (npm install -g nativescript
), you can create an iOS Widget with a single command:
$ ns widget ios
This will allow you to create a Home Screen Widget, a Live Activity on the lock screen or a combination of both.
ns widget ios
The widget command generates all the necessary files for your NativeScript project to develop iOS widgets. The setup includes a fully functioning hypothetical pizza delivery widget which you can learn from and customize for your own needs.
The command will prompt to name the widget and choose a type. We will provide a custom name to outline exactly what is generated to explain each file.
$ ns widget ios
? What name would you like for this widget? (Default is 'widget') › pizza
? What type of widget would you like? › - Use arrow-keys. Return to submit.
Live Activity
❯ Live Activity with Home Screen Widget - This will create a Live Activity that will display on the iOS Lock Screen with ability to also display a Home Screen Widget.
Home Screen Widget
Once the choice is made, the widget will be generated. Based on the above responses, you would see a few followup steps:
Created Shared Resources: Shared_Resources/iOS/SharedWidget.
🚀 Your widget is now ready to develop: App_Resources/iOS/extensions/pizza.
Followup steps:
- Check App_Resources/iOS/build.xcconfig uses IPHONEOS_DEPLOYMENT_TARGET=17 or higher.
- Update App_Resources/iOS/extensions/provisioning.json with your profile id.
- Customize App_Resources/iOS/extensions/pizza/PizzaLiveActivity.swift for your display.
- Customize Shared_Resources/iOS/SharedWidget/Sources/SharedWidget/PizzaModel.swift for your data.
Let's discuss each note by outlining everything that was generated:
App_Resources/iOS/app.entitlements
: Includes the App Groups capability for shared data between your app and widget. If one doesn't exist, it will be created for you.App_Resources/iOS/extensions/pizza/extension.json
: Xcode build configuration details. This is where additional frameworks, if desired, for your widget can also be included in theframeworks
collection at the top.App_Resources/iOS/extensions/pizza/Info.plist
: The widget's info property list.App_Resources/iOS/extensions/pizza/pizza.entitlements
: Similar to the app.entitlements, this also includes the App Groups capability for shared data between your app and widget.App_Resources/iOS/extensions/pizza/PizzaBundle.swift
: This allows different widget features to be bundled together. For example, when choosing a Live Activity with a Home Screen Widget, both will be listed as part of the widget bundle here.App_Resources/iOS/extensions/pizza/PizzaHomeScreenWidget.swift
: The Home Screen Widget itself. This is where the view is defined as well as the Timeline which determines how data should be provided to the view. It comes already setup to use data from shared app/widget data which you can customize further.App_Resources/iOS/extensions/pizza/PizzaLiveActivity.swift
: The Live Activity to show on the lock screen. The view is defined viaLockScreenView
and also provides example customizations to the iPhone Dynamic Island.App_Resources/iOS/extensions/pizza/PrivacyInfo.xcprivacy
: The privacy policy for the widget. Refence documentation can be found here.App_Resources/iOS/extensions/provisioning.json
: The provisioning profile configured to use with the widget id. On first generation, a placeholder is inserted however you can update this value to the provision profile needed.
Provisioning Profiles
open ~/Library/Developer/Xcode/UserData/Provisioning\ Profiles
and sort by modified date; this will allow you to find the profile id auto generated by xcode for your widget.
App_Resources/iOS/src/AppleWidgetUtils.swift
: This provides various static utilities for your NativeScript app to start, update and cancel live activities, as well as initiate widget updates and interact with shared data between your app and the widget.Shared_Resources/iOS/SharedWidget/Sources/SharedWidget/PizzaModel.swift
: This model is the contract of data between your app and your widget.
Shared Model Data
Because your app and widget are separate processes yet need to share the same model data to interact, Shared_Resources/iOS/SharedWidget
is created as a local shared Swift package and auto configured via nativescript.config
to share between your app and widget. This allows you to avoid unnecessary code duplication.
Your projects references.d.ts
are also annotated to include strong types for AppleWidgetUtils
usage from your TypeScript codebase:
/**
* Customize for your own Apple Widget Data
*/
declare interface AppleWidgetModelData {
numberOfPizzas: number
totalAmount: string
message: string
deliveryTime: number
}
declare class AppleWidgetUtils extends NSObject {
static startActivity(data: AppleWidgetModelData): void
static updateActivity(
data: Pick<AppleWidgetModelData, 'message' | 'deliveryTime'>,
): void
static cancelActivity(data: Pick<AppleWidgetModelData, 'message'>): void
static updateWidget(): void
static updateDataWithKey(key: string, data: string): void
static getDataWithKey(key: string): string
static removeDataWithKey(key: string): void
}
Based on your own data needs, you can customize AppleWidgetModelData
and the method signatures of AppleWidgetUtils
to suit your case.
All shared group data between your app and widget are intended to be a string value so when using AppleWidgetUtils.updateDataWithKey
with structured data, you can stringify it:
AppleWidgetUtils.updateDataWithKey(
'widgetData',
JSON.stringify({
pizzas: ['Pepperoni', 'Supreme', 'Hawaiian', 'Meat Lovers', 'Margherita'],
orderTime: this.orderTime(),
delivered: false,
}),
)
This data is always decoded in the widget for it's own data purposes.
Widget Development
All of the generated files are intended to be customized for your needs while at the same time giving you enough to follow to be successful at widget creation.
Sample Project
A helpful sample project is available here. It utilizes everything that ns widget ios
provides for you to learn from.
Resources
Additional features can be discussed anytime:
- https://github.com/orgs/NativeScript/discussions
- https://github.com/NativeScript/NativeScript/issues/10703
Widget extensions have been supported with NativeScript for several years. Prior to 8.9, they required a number of manual steps. We'll include the following resources for additional context:
- https://blog.nativescript.org/add-home-screen-widget
- https://www.bryanleetc.com/creating-a-share-extension-in-nativescript/
- https://blog.nativescript.org/making-a-today-widget-in-ios-with-nativescript-and-ui-for-nativescript
- https://old.docs.nativescript.org/tooling/ios-app-extensions.html
Troubleshooting
Several common cases could occur while developing widgets.
Minimum version targeting
The widget generator expects iOS 17 minimum.
If you encounter errors similar to the following:
App_Resources/iOS/extensions/widget/WidgetBundle.swift:7:3: error: 'WidgetHomeScreen' is only available in application extensions for iOS 17.0 or newer
Add the following line to your App_Resources/iOS/build.xcconfig
:
IPHONEOS_DEPLOYMENT_TARGET = 17;
- Previous
- Platform Version Handling