Skip to content

Commit 0323f9a

Browse files
committed
feat: ns widget ios
1 parent 3bacbba commit 0323f9a

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed

content/guide/widgets-ios.md

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
title: Developing Widgets for iOS
3+
---
4+
5+
[Widgets](https://developer.apple.com/design/human-interface-guidelines/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.
6+
7+
> 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.
8+
9+
With NativeScript 8.9 CLI (`npm install -g nativescript`), you can create an iOS Widget with a single command:
10+
11+
```bash
12+
$ ns widget ios
13+
```
14+
15+
This will allow you to create a Home Screen Widget, a Live Activity on the lock screen or a combination of both.
16+
17+
## ns widget ios
18+
19+
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.
20+
21+
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.
22+
23+
```bash
24+
$ ns widget ios
25+
? What name would you like for this widget? (Default is 'widget') › pizza
26+
? What type of widget would you like? › - Use arrow-keys. Return to submit.
27+
Live Activity
28+
❯ 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.
29+
Home Screen Widget
30+
```
31+
32+
Once the choice is made, the widget will be generated. Based on the above responses, you would see a few followup steps:
33+
34+
```bash
35+
Created Shared Resources: Shared_Resources/iOS/SharedWidget.
36+
37+
🚀 Your widget is now ready to develop: App_Resources/iOS/extensions/pizza.
38+
39+
Followup steps:
40+
41+
- Check App_Resources/iOS/build.xcconfig uses IPHONEOS_DEPLOYMENT_TARGET=17 or higher.
42+
- Update App_Resources/iOS/extensions/provisioning.json with your profile id.
43+
- Customize App_Resources/iOS/extensions/pizza/PizzaLiveActivity.swift for your display.
44+
- Customize Shared_Resources/iOS/SharedWidget/Sources/SharedWidget/PizzaModel.swift for your data.
45+
```
46+
47+
Let's discuss each note by outlining everything that was generated:
48+
49+
- `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.*
50+
- `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.
51+
- `App_Resources/iOS/extensions/pizza/Info.plist`: The widget's info property list.
52+
- `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.
53+
- `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.
54+
- `App_Resources/iOS/extensions/pizza/PizzaHomeScreenWidget.swift`: The Home Screen Widget itself. This is where the view is defined as well as the [Timeline](https://developer.apple.com/documentation/widgetkit/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.
55+
- `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](https://support.apple.com/guide/iphone/use-the-dynamic-island-iph28f50d10d/ios).
56+
- `App_Resources/iOS/extensions/pizza/PrivacyInfo.xcprivacy`: The privacy policy for the widget. Refence documentation can be found [here](https://developer.apple.com/documentation/bundleresources/privacy-manifest-files).
57+
- `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.
58+
59+
::: tip Provisioning Profiles
60+
`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.
61+
:::
62+
63+
- `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.
64+
- `Shared_Resources/iOS/SharedWidget/Sources/SharedWidget/PizzaModel.swift`: This model is the contract of data between your app and your widget.
65+
66+
::: info Shared Model Data
67+
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.
68+
:::
69+
70+
Your projects `references.d.ts` are also annotated to include strong types for `AppleWidgetUtils` usage from your TypeScript codebase:
71+
72+
```ts
73+
/**
74+
* Customize for your own Apple Widget Data
75+
*/
76+
declare interface AppleWidgetModelData {
77+
numberOfPizzas: number;
78+
totalAmount: string;
79+
message: string;
80+
deliveryTime: number;
81+
}
82+
declare class AppleWidgetUtils extends NSObject {
83+
static startActivity(data: AppleWidgetModelData): void;
84+
static updateActivity(
85+
data: Pick<AppleWidgetModelData, "message" | "deliveryTime">
86+
): void;
87+
static cancelActivity(data: Pick<AppleWidgetModelData, "message">): void;
88+
static updateWidget(): void;
89+
static updateDataWithKey(key: string, data: string): void;
90+
static getDataWithKey(key: string): string;
91+
static removeDataWithKey(key: string): void;
92+
}
93+
```
94+
95+
Based on your own data needs, you can customize `AppleWidgetModelData` and the method signatures of `AppleWidgetUtils` to suit your case.
96+
97+
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:
98+
99+
```ts
100+
AppleWidgetUtils.updateDataWithKey(
101+
"widgetData",
102+
JSON.stringify({
103+
pizzas: [
104+
"Pepperoni",
105+
"Supreme",
106+
"Hawaiian",
107+
"Meat Lovers",
108+
"Margherita",
109+
],
110+
orderTime: this.orderTime(),
111+
delivered: false,
112+
})
113+
);
114+
```
115+
116+
This data is always decoded in the widget for it's own data purposes.
117+
118+
::: tip Widget Development
119+
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.
120+
:::
121+
122+
## Sample Project
123+
124+
A helpful sample project is available [here](https://github.com/NativeScript/widget-ios-example). It utilizes everything that `ns widget ios` provides for you to learn from.
125+
126+
## Resources
127+
128+
Additional features can be discussed anytime:
129+
- https://github.com/orgs/NativeScript/discussions
130+
- https://github.com/NativeScript/NativeScript/issues/10703
131+
132+
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:
133+
- https://blog.nativescript.org/add-home-screen-widget
134+
- https://www.bryanleetc.com/creating-a-share-extension-in-nativescript/
135+
- https://blog.nativescript.org/making-a-today-widget-in-ios-with-nativescript-and-ui-for-nativescript
136+
- https://old.docs.nativescript.org/tooling/ios-app-extensions.html
137+
138+
## Troubleshooting
139+
140+
Several common cases could occur while developing widgets.
141+
142+
### Minimum version targeting
143+
144+
The widget generator expects iOS 17 minimum.
145+
146+
If you encounter errors similar to the following:
147+
148+
```
149+
App_Resources/iOS/extensions/widget/WidgetBundle.swift:7:3: error: 'WidgetHomeScreen' is only available in application extensions for iOS 17.0 or newer
150+
```
151+
152+
Add the following line to your `App_Resources/iOS/build.xcconfig`:
153+
154+
```
155+
IPHONEOS_DEPLOYMENT_TARGET = 17;
156+
```
157+

content/sidebar.ts

+4
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ export default [
299299
{
300300
text: 'Platform Version Handling',
301301
link: '/guide/platform-version-handling',
302+
},
303+
{
304+
text: 'Widgets for iOS',
305+
link: '/guide/widgets-ios',
302306
}
303307
],
304308
},

0 commit comments

Comments
 (0)