🚀 8.9 Released! → ⚡️ New Node-API Engine Preview, 📲 ns widget ios, 💅 Tailwind v4 and more...
Read Announcement

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:

bash
$ 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.

bash
$ 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:

bash
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 the frameworks 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 via LockScreenView 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:

ts
/**
 * 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:

ts
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:

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:

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:

bash
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:

bash
IPHONEOS_DEPLOYMENT_TARGET = 17;