buildanything 1.7.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +55 -0
- package/agents/ios-app-review-guardian.md +49 -0
- package/agents/ios-foundation-models-specialist.md +46 -0
- package/agents/ios-storekit-specialist.md +52 -0
- package/agents/ios-swift-architect.md +102 -0
- package/agents/ios-swift-search.md +130 -0
- package/agents/ios-swift-ui-design.md +104 -0
- package/commands/build.md +80 -176
- package/commands/fix.md +65 -0
- package/commands/setup.md +73 -0
- package/commands/ux-review.md +63 -0
- package/commands/verify.md +72 -0
- package/hooks/session-start +18 -1
- package/package.json +5 -2
- package/protocols/brainstorm.md +99 -0
- package/protocols/build-fix.md +52 -0
- package/protocols/cleanup.md +54 -0
- package/protocols/design.md +269 -0
- package/protocols/eval-harness.md +61 -0
- package/protocols/fake-data-detector.md +64 -0
- package/protocols/ios-context.md +235 -0
- package/protocols/ios-frameworks-map.md +323 -0
- package/protocols/ios-phase-branches.md +162 -0
- package/protocols/ios-preflight.md +27 -0
- package/protocols/metric-loop.md +93 -0
- package/protocols/planning.md +87 -0
- package/protocols/smoke-test.md +110 -0
- package/protocols/verify.md +67 -0
- package/protocols/web-phase-branches.md +201 -0
- package/skills/ios/_VENDORED.md +60 -0
- package/skills/ios/activitykit/LICENSE +131 -0
- package/skills/ios/activitykit/SKILL.md +505 -0
- package/skills/ios/activitykit/references/activitykit-patterns.md +868 -0
- package/skills/ios/app-intents/LICENSE +131 -0
- package/skills/ios/app-intents/SKILL.md +494 -0
- package/skills/ios/app-intents/references/appintents-advanced.md +1076 -0
- package/skills/ios/apple-on-device-ai/LICENSE +131 -0
- package/skills/ios/apple-on-device-ai/SKILL.md +505 -0
- package/skills/ios/apple-on-device-ai/references/coreml-conversion.md +425 -0
- package/skills/ios/apple-on-device-ai/references/coreml-optimization.md +344 -0
- package/skills/ios/apple-on-device-ai/references/foundation-models.md +508 -0
- package/skills/ios/apple-on-device-ai/references/mlx-swift.md +285 -0
- package/skills/ios/ios-26-platform/SKILL.md +53 -0
- package/skills/ios/ios-26-platform/references/automatic-adoption.md +161 -0
- package/skills/ios/ios-26-platform/references/backward-compat.md +238 -0
- package/skills/ios/ios-26-platform/references/liquid-glass.md +255 -0
- package/skills/ios/ios-26-platform/references/swiftui-apis.md +277 -0
- package/skills/ios/ios-26-platform/references/toolbar-navigation.md +250 -0
- package/skills/ios/ios-bootstrap/SKILL.md +98 -0
- package/skills/ios/ios-bootstrap/references/apple-docs-mcp-config.md +28 -0
- package/skills/ios/ios-bootstrap/references/new-project-dialog.md +41 -0
- package/skills/ios/ios-bootstrap/references/xcode-mcp-config.md +29 -0
- package/skills/ios/ios-debugger-agent/LICENSE +21 -0
- package/skills/ios/ios-debugger-agent/SKILL.md +58 -0
- package/skills/ios/ios-debugger-agent/agents/openai.yaml +4 -0
- package/skills/ios/ios-entitlements-generator/SKILL.md +47 -0
- package/skills/ios/ios-hig/SKILL.md +41 -0
- package/skills/ios/ios-hig/references/accessibility.md +81 -0
- package/skills/ios/ios-hig/references/content.md +142 -0
- package/skills/ios/ios-hig/references/feedback.md +123 -0
- package/skills/ios/ios-hig/references/interaction.md +199 -0
- package/skills/ios/ios-hig/references/performance-platform.md +129 -0
- package/skills/ios/ios-hig/references/privacy-permissions.md +181 -0
- package/skills/ios/ios-hig/references/visual-design.md +84 -0
- package/skills/ios/ios-info-plist-hardening/SKILL.md +130 -0
- package/skills/ios/ios-maestro-flow-author/SKILL.md +68 -0
- package/skills/ios/ios-maestro-flow-author/references/input-and-scroll.yaml +17 -0
- package/skills/ios/ios-maestro-flow-author/references/modal-and-dismiss.yaml +14 -0
- package/skills/ios/ios-maestro-flow-author/references/onboarding-flow.yaml +16 -0
- package/skills/ios/ios-maestro-flow-author/references/tab-navigation.yaml +13 -0
- package/skills/ios/ios-maestro-flow-author/references/tap-and-assert.yaml +9 -0
- package/skills/ios/swift-accessibility/LICENSE +21 -0
- package/skills/ios/swift-accessibility/SKILL.md +371 -0
- package/skills/ios/swift-accessibility/examples/before-after-appkit.md +446 -0
- package/skills/ios/swift-accessibility/examples/before-after-swiftui.md +441 -0
- package/skills/ios/swift-accessibility/examples/before-after-uikit.md +464 -0
- package/skills/ios/swift-accessibility/references/assistive-access.md +441 -0
- package/skills/ios/swift-accessibility/references/display-settings.md +491 -0
- package/skills/ios/swift-accessibility/references/dynamic-type.md +420 -0
- package/skills/ios/swift-accessibility/references/media-accessibility.md +421 -0
- package/skills/ios/swift-accessibility/references/motor-input.md +393 -0
- package/skills/ios/swift-accessibility/references/nutrition-labels.md +362 -0
- package/skills/ios/swift-accessibility/references/platform-specifics.md +515 -0
- package/skills/ios/swift-accessibility/references/semantic-structure.md +585 -0
- package/skills/ios/swift-accessibility/references/testing-auditing.md +507 -0
- package/skills/ios/swift-accessibility/references/voice-control.md +317 -0
- package/skills/ios/swift-accessibility/references/voiceover-swiftui.md +584 -0
- package/skills/ios/swift-accessibility/references/voiceover-uikit.md +519 -0
- package/skills/ios/swift-accessibility/references/wcag-mapping.md +167 -0
- package/skills/ios/swift-accessibility/resources/audit-template.swift +128 -0
- package/skills/ios/swift-accessibility/resources/qa-checklist.md +258 -0
- package/skills/ios/swift-concurrency/LICENSE +21 -0
- package/skills/ios/swift-concurrency/SKILL.md +171 -0
- package/skills/ios/swift-concurrency/references/_index.md +50 -0
- package/skills/ios/swift-concurrency/references/actors.md +660 -0
- package/skills/ios/swift-concurrency/references/async-algorithms.md +847 -0
- package/skills/ios/swift-concurrency/references/async-await-basics.md +266 -0
- package/skills/ios/swift-concurrency/references/async-sequences.md +710 -0
- package/skills/ios/swift-concurrency/references/core-data.md +560 -0
- package/skills/ios/swift-concurrency/references/glossary.md +135 -0
- package/skills/ios/swift-concurrency/references/linting.md +155 -0
- package/skills/ios/swift-concurrency/references/memory-management.md +569 -0
- package/skills/ios/swift-concurrency/references/migration.md +1104 -0
- package/skills/ios/swift-concurrency/references/performance.md +593 -0
- package/skills/ios/swift-concurrency/references/sendable.md +598 -0
- package/skills/ios/swift-concurrency/references/tasks.md +636 -0
- package/skills/ios/swift-concurrency/references/testing.md +592 -0
- package/skills/ios/swift-concurrency/references/threading.md +495 -0
- package/skills/ios/swift-security-expert/LICENSE +21 -0
- package/skills/ios/swift-security-expert/SKILL.md +470 -0
- package/skills/ios/swift-security-expert/references/biometric-authentication.md +565 -0
- package/skills/ios/swift-security-expert/references/certificate-trust.md +592 -0
- package/skills/ios/swift-security-expert/references/common-anti-patterns.md +690 -0
- package/skills/ios/swift-security-expert/references/compliance-owasp-mapping.md +537 -0
- package/skills/ios/swift-security-expert/references/credential-storage-patterns.md +721 -0
- package/skills/ios/swift-security-expert/references/cryptokit-public-key.md +505 -0
- package/skills/ios/swift-security-expert/references/cryptokit-symmetric.md +497 -0
- package/skills/ios/swift-security-expert/references/keychain-access-control.md +508 -0
- package/skills/ios/swift-security-expert/references/keychain-fundamentals.md +596 -0
- package/skills/ios/swift-security-expert/references/keychain-item-classes.md +476 -0
- package/skills/ios/swift-security-expert/references/keychain-sharing.md +458 -0
- package/skills/ios/swift-security-expert/references/migration-legacy-stores.md +727 -0
- package/skills/ios/swift-security-expert/references/secure-enclave.md +539 -0
- package/skills/ios/swift-security-expert/references/testing-security-code.md +781 -0
- package/skills/ios/swift-testing-expert/LICENSE +21 -0
- package/skills/ios/swift-testing-expert/SKILL.md +79 -0
- package/skills/ios/swift-testing-expert/references/_index.md +12 -0
- package/skills/ios/swift-testing-expert/references/async-testing-and-waiting.md +127 -0
- package/skills/ios/swift-testing-expert/references/expectations.md +145 -0
- package/skills/ios/swift-testing-expert/references/fundamentals.md +141 -0
- package/skills/ios/swift-testing-expert/references/migration-from-xctest.md +127 -0
- package/skills/ios/swift-testing-expert/references/parallelization-and-isolation.md +95 -0
- package/skills/ios/swift-testing-expert/references/parameterized-testing.md +284 -0
- package/skills/ios/swift-testing-expert/references/performance-and-best-practices.md +187 -0
- package/skills/ios/swift-testing-expert/references/traits-and-tags.md +114 -0
- package/skills/ios/swift-testing-expert/references/xcode-workflows.md +70 -0
- package/skills/ios/swiftdata-pro/LICENSE +21 -0
- package/skills/ios/swiftdata-pro/SKILL.md +102 -0
- package/skills/ios/swiftdata-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.png +0 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.svg +29 -0
- package/skills/ios/swiftdata-pro/references/class-inheritance.md +104 -0
- package/skills/ios/swiftdata-pro/references/cloudkit.md +10 -0
- package/skills/ios/swiftdata-pro/references/core-rules.md +20 -0
- package/skills/ios/swiftdata-pro/references/indexing.md +27 -0
- package/skills/ios/swiftdata-pro/references/predicates.md +73 -0
- package/skills/ios/swiftui-design-principles/AGENTS.md +21 -0
- package/skills/ios/swiftui-design-principles/LICENSE +21 -0
- package/skills/ios/swiftui-design-principles/README.md +41 -0
- package/skills/ios/swiftui-design-principles/SKILL.md +605 -0
- package/skills/ios/swiftui-design-principles/metadata.json +10 -0
- package/skills/ios/swiftui-liquid-glass/LICENSE +21 -0
- package/skills/ios/swiftui-liquid-glass/SKILL.md +95 -0
- package/skills/ios/swiftui-liquid-glass/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-liquid-glass/references/liquid-glass.md +280 -0
- package/skills/ios/swiftui-performance-audit/LICENSE +21 -0
- package/skills/ios/swiftui-performance-audit/SKILL.md +111 -0
- package/skills/ios/swiftui-performance-audit/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-performance-audit/references/code-smells.md +150 -0
- package/skills/ios/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
- package/skills/ios/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
- package/skills/ios/swiftui-performance-audit/references/profiling-intake.md +44 -0
- package/skills/ios/swiftui-performance-audit/references/report-template.md +47 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
- package/skills/ios/swiftui-pro/LICENSE +21 -0
- package/skills/ios/swiftui-pro/SKILL.md +108 -0
- package/skills/ios/swiftui-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
- package/skills/ios/swiftui-pro/references/accessibility.md +13 -0
- package/skills/ios/swiftui-pro/references/api.md +39 -0
- package/skills/ios/swiftui-pro/references/data.md +43 -0
- package/skills/ios/swiftui-pro/references/design.md +31 -0
- package/skills/ios/swiftui-pro/references/hygiene.md +9 -0
- package/skills/ios/swiftui-pro/references/navigation.md +14 -0
- package/skills/ios/swiftui-pro/references/performance.md +46 -0
- package/skills/ios/swiftui-pro/references/swift.md +56 -0
- package/skills/ios/swiftui-pro/references/views.md +35 -0
- package/skills/ios/swiftui-ui-patterns/LICENSE +21 -0
- package/skills/ios/swiftui-ui-patterns/SKILL.md +100 -0
- package/skills/ios/swiftui-ui-patterns/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-ui-patterns/references/app-wiring.md +201 -0
- package/skills/ios/swiftui-ui-patterns/references/async-state.md +96 -0
- package/skills/ios/swiftui-ui-patterns/references/components-index.md +50 -0
- package/skills/ios/swiftui-ui-patterns/references/controls.md +57 -0
- package/skills/ios/swiftui-ui-patterns/references/deeplinks.md +66 -0
- package/skills/ios/swiftui-ui-patterns/references/focus.md +90 -0
- package/skills/ios/swiftui-ui-patterns/references/form.md +97 -0
- package/skills/ios/swiftui-ui-patterns/references/grids.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/haptics.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/input-toolbar.md +51 -0
- package/skills/ios/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/list.md +86 -0
- package/skills/ios/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
- package/skills/ios/swiftui-ui-patterns/references/macos-settings.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/matched-transitions.md +59 -0
- package/skills/ios/swiftui-ui-patterns/references/media.md +73 -0
- package/skills/ios/swiftui-ui-patterns/references/menu-bar.md +101 -0
- package/skills/ios/swiftui-ui-patterns/references/navigationstack.md +159 -0
- package/skills/ios/swiftui-ui-patterns/references/overlay.md +45 -0
- package/skills/ios/swiftui-ui-patterns/references/performance.md +62 -0
- package/skills/ios/swiftui-ui-patterns/references/previews.md +48 -0
- package/skills/ios/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
- package/skills/ios/swiftui-ui-patterns/references/scrollview.md +87 -0
- package/skills/ios/swiftui-ui-patterns/references/searchable.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/sheets.md +155 -0
- package/skills/ios/swiftui-ui-patterns/references/split-views.md +72 -0
- package/skills/ios/swiftui-ui-patterns/references/tabview.md +114 -0
- package/skills/ios/swiftui-ui-patterns/references/theming.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/title-menus.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/top-bar.md +49 -0
- package/skills/ios/swiftui-view-refactor/LICENSE +21 -0
- package/skills/ios/swiftui-view-refactor/SKILL.md +207 -0
- package/skills/ios/swiftui-view-refactor/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-view-refactor/references/mv-patterns.md +161 -0
- package/skills/ios/widgetkit/LICENSE +131 -0
- package/skills/ios/widgetkit/SKILL.md +502 -0
- package/skills/ios/widgetkit/references/widgetkit-advanced.md +871 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
Required Notice: Copyright (c) 2025 dpearson2699 (https://github.com/dpearson2699)
|
|
2
|
+
|
|
3
|
+
# PolyForm Perimeter License 1.0.0
|
|
4
|
+
|
|
5
|
+
<https://polyformproject.org/licenses/perimeter/1.0.0>
|
|
6
|
+
|
|
7
|
+
## Acceptance
|
|
8
|
+
|
|
9
|
+
In order to get any license under these terms, you must agree
|
|
10
|
+
to them as both strict obligations and conditions to all
|
|
11
|
+
your licenses.
|
|
12
|
+
|
|
13
|
+
## Copyright License
|
|
14
|
+
|
|
15
|
+
The licensor grants you a copyright license for the
|
|
16
|
+
software to do everything you might do with the software
|
|
17
|
+
that would otherwise infringe the licensor's copyright
|
|
18
|
+
in it for any permitted purpose. However, you may
|
|
19
|
+
only distribute the software according to [Distribution
|
|
20
|
+
License](#distribution-license) and make changes or new works
|
|
21
|
+
based on the software according to [Changes and New Works
|
|
22
|
+
License](#changes-and-new-works-license).
|
|
23
|
+
|
|
24
|
+
## Distribution License
|
|
25
|
+
|
|
26
|
+
The licensor grants you an additional copyright license
|
|
27
|
+
to distribute copies of the software. Your license
|
|
28
|
+
to distribute covers distributing the software with
|
|
29
|
+
changes and new works permitted by [Changes and New Works
|
|
30
|
+
License](#changes-and-new-works-license).
|
|
31
|
+
|
|
32
|
+
## Notices
|
|
33
|
+
|
|
34
|
+
You must ensure that anyone who gets a copy of any part of
|
|
35
|
+
the software from you also gets a copy of these terms or the
|
|
36
|
+
URL for them above, as well as copies of any plain-text lines
|
|
37
|
+
beginning with `Required Notice:` that the licensor provided
|
|
38
|
+
with the software. For example:
|
|
39
|
+
|
|
40
|
+
> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
|
|
41
|
+
|
|
42
|
+
## Changes and New Works License
|
|
43
|
+
|
|
44
|
+
The licensor grants you an additional copyright license to
|
|
45
|
+
make changes and new works based on the software for any
|
|
46
|
+
permitted purpose.
|
|
47
|
+
|
|
48
|
+
## Patent License
|
|
49
|
+
|
|
50
|
+
The licensor grants you a patent license for the software that
|
|
51
|
+
covers patent claims the licensor can license, or becomes able
|
|
52
|
+
to license, that you would infringe by using the software.
|
|
53
|
+
|
|
54
|
+
## Noncompete
|
|
55
|
+
|
|
56
|
+
Any purpose is a permitted purpose, except for providing to
|
|
57
|
+
others any product that competes with the software.
|
|
58
|
+
|
|
59
|
+
## Competition
|
|
60
|
+
|
|
61
|
+
If you use this software to market a product as a substitute
|
|
62
|
+
for the functionality or value of the software, it competes
|
|
63
|
+
with the software. A product may compete regardless how it is
|
|
64
|
+
designed or deployed. For example, a product may compete even
|
|
65
|
+
if it provides its functionality via any kind of interface
|
|
66
|
+
(including services, libraries or plug-ins), even if it is
|
|
67
|
+
ported to a different platforms or programming languages,
|
|
68
|
+
and even if it is provided free of charge.
|
|
69
|
+
|
|
70
|
+
## Fair Use
|
|
71
|
+
|
|
72
|
+
You may have "fair use" rights for the software under the
|
|
73
|
+
law. These terms do not limit them.
|
|
74
|
+
|
|
75
|
+
## No Other Rights
|
|
76
|
+
|
|
77
|
+
These terms do not allow you to sublicense or transfer any of
|
|
78
|
+
your licenses to anyone else, or prevent the licensor from
|
|
79
|
+
granting licenses to anyone else. These terms do not imply
|
|
80
|
+
any other licenses.
|
|
81
|
+
|
|
82
|
+
## Patent Defense
|
|
83
|
+
|
|
84
|
+
If you make any written claim that the software infringes or
|
|
85
|
+
contributes to infringement of any patent, your patent license
|
|
86
|
+
for the software granted under these terms ends immediately. If
|
|
87
|
+
your company makes such a claim, your patent license ends
|
|
88
|
+
immediately for work on behalf of your company.
|
|
89
|
+
|
|
90
|
+
## Violations
|
|
91
|
+
|
|
92
|
+
The first time you are notified in writing that you have
|
|
93
|
+
violated any of these terms, or done anything with the software
|
|
94
|
+
not covered by your licenses, your licenses can nonetheless
|
|
95
|
+
continue if you come into full compliance with these terms,
|
|
96
|
+
and take practical steps to correct past violations, within
|
|
97
|
+
32 days of receiving notice. Otherwise, all your licenses
|
|
98
|
+
end immediately.
|
|
99
|
+
|
|
100
|
+
## No Liability
|
|
101
|
+
|
|
102
|
+
***As far as the law allows, the software comes as is, without
|
|
103
|
+
any warranty or condition, and the licensor will not be liable
|
|
104
|
+
to you for any damages arising out of these terms or the use
|
|
105
|
+
or nature of the software, under any kind of legal claim.***
|
|
106
|
+
|
|
107
|
+
## Definitions
|
|
108
|
+
|
|
109
|
+
The **licensor** is the individual or entity offering these
|
|
110
|
+
terms, and the **software** is the software the licensor makes
|
|
111
|
+
available under these terms.
|
|
112
|
+
|
|
113
|
+
A **product** can be a good or service, or a combination
|
|
114
|
+
of them.
|
|
115
|
+
|
|
116
|
+
**You** refers to the individual or entity agreeing to these
|
|
117
|
+
terms.
|
|
118
|
+
|
|
119
|
+
**Your company** is any legal entity, sole proprietorship,
|
|
120
|
+
or other kind of organization that you work for, plus all
|
|
121
|
+
organizations that have control over, are under the control of,
|
|
122
|
+
or are under common control with that organization. **Control**
|
|
123
|
+
means ownership of substantially all the assets of an entity,
|
|
124
|
+
or the power to direct its management and policies by vote,
|
|
125
|
+
contract, or otherwise. Control can be direct or indirect.
|
|
126
|
+
|
|
127
|
+
**Your licenses** are all the licenses granted to you for the
|
|
128
|
+
software under these terms.
|
|
129
|
+
|
|
130
|
+
**Use** means anything you do with the software requiring one
|
|
131
|
+
of your licenses.
|
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: activitykit
|
|
3
|
+
description: "Implement, review, or improve Live Activities and Dynamic Island experiences in iOS apps using ActivityKit. Use when building real-time updating widgets for the Lock Screen and Dynamic Island — delivery tracking, sports scores, ride-sharing status, workout timers, media playback, or any time-sensitive information that updates in real time. Also use when working with ActivityKit, ActivityAttributes, Activity lifecycle (request/update/end), Dynamic Island layouts (compact/minimal/expanded), push-to-update Live Activities, or Lock Screen live widgets."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ActivityKit
|
|
7
|
+
|
|
8
|
+
Build real-time, glanceable experiences on the Lock Screen, Dynamic Island,
|
|
9
|
+
StandBy, CarPlay, and a paired Mac using ActivityKit. Patterns target iOS 26+
|
|
10
|
+
with Swift 6.3, backward-compatible to iOS 16.1 unless noted.
|
|
11
|
+
|
|
12
|
+
See [references/activitykit-patterns.md](references/activitykit-patterns.md) for complete code patterns including push payload formats, concurrent activities, state observation, and testing.
|
|
13
|
+
|
|
14
|
+
## Contents
|
|
15
|
+
|
|
16
|
+
- [Workflow](#workflow)
|
|
17
|
+
- [ActivityAttributes Definition](#activityattributes-definition)
|
|
18
|
+
- [Activity Lifecycle](#activity-lifecycle)
|
|
19
|
+
- [Lock Screen Presentation](#lock-screen-presentation)
|
|
20
|
+
- [Dynamic Island](#dynamic-island)
|
|
21
|
+
- [Push-to-Update](#push-to-update)
|
|
22
|
+
- [iOS 26 Additions](#ios-26-additions)
|
|
23
|
+
- [Common Mistakes](#common-mistakes)
|
|
24
|
+
- [Review Checklist](#review-checklist)
|
|
25
|
+
- [References](#references)
|
|
26
|
+
|
|
27
|
+
## Workflow
|
|
28
|
+
|
|
29
|
+
### 1. Create a new Live Activity
|
|
30
|
+
|
|
31
|
+
1. Add `NSSupportsLiveActivities = YES` to the host app's Info.plist.
|
|
32
|
+
2. Define an `ActivityAttributes` struct with a nested `ContentState`.
|
|
33
|
+
3. Create an `ActivityConfiguration` in the widget bundle with Lock Screen
|
|
34
|
+
content and Dynamic Island closures.
|
|
35
|
+
4. Start the activity with `Activity.request(attributes:content:pushType:)`.
|
|
36
|
+
5. Update with `activity.update(_:)` and end with `activity.end(_:dismissalPolicy:)`.
|
|
37
|
+
6. Forward push tokens to your server for remote updates.
|
|
38
|
+
|
|
39
|
+
### 2. Review existing Live Activity code
|
|
40
|
+
|
|
41
|
+
Run through the Review Checklist at the end of this document.
|
|
42
|
+
|
|
43
|
+
## ActivityAttributes Definition
|
|
44
|
+
|
|
45
|
+
Define both static data (immutable for the activity lifetime) and dynamic
|
|
46
|
+
`ContentState` (changes with each update). Keep `ContentState` small because
|
|
47
|
+
the entire struct is serialized on every update and push payload.
|
|
48
|
+
|
|
49
|
+
```swift
|
|
50
|
+
import ActivityKit
|
|
51
|
+
|
|
52
|
+
struct DeliveryAttributes: ActivityAttributes {
|
|
53
|
+
// Static -- set once at activity creation, never changes
|
|
54
|
+
var orderNumber: Int
|
|
55
|
+
var restaurantName: String
|
|
56
|
+
|
|
57
|
+
// Dynamic -- updated throughout the activity lifetime
|
|
58
|
+
struct ContentState: Codable, Hashable {
|
|
59
|
+
var driverName: String
|
|
60
|
+
var estimatedDeliveryTime: ClosedRange<Date>
|
|
61
|
+
var currentStep: DeliveryStep
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
enum DeliveryStep: String, Codable, Hashable, CaseIterable {
|
|
66
|
+
case confirmed, preparing, pickedUp, delivering, delivered
|
|
67
|
+
|
|
68
|
+
var icon: String {
|
|
69
|
+
switch self {
|
|
70
|
+
case .confirmed: "checkmark.circle"
|
|
71
|
+
case .preparing: "frying.pan"
|
|
72
|
+
case .pickedUp: "bag.fill"
|
|
73
|
+
case .delivering: "box.truck.fill"
|
|
74
|
+
case .delivered: "house.fill"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Stale Date
|
|
81
|
+
|
|
82
|
+
Set `staleDate` on `ActivityContent` to tell the system when content becomes outdated. The system sets `context.isStale` to `true` after this date; show fallback UI (e.g., "Updating...") in your views.
|
|
83
|
+
|
|
84
|
+
```swift
|
|
85
|
+
let content = ActivityContent(
|
|
86
|
+
state: state,
|
|
87
|
+
staleDate: Date().addingTimeInterval(300), // stale after 5 minutes
|
|
88
|
+
relevanceScore: 75
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Activity Lifecycle
|
|
93
|
+
|
|
94
|
+
### Starting
|
|
95
|
+
|
|
96
|
+
Use `Activity.request` to create and display a Live Activity. Pass `.token` as
|
|
97
|
+
the `pushType` to enable remote updates via APNs.
|
|
98
|
+
|
|
99
|
+
```swift
|
|
100
|
+
let attributes = DeliveryAttributes(orderNumber: 42, restaurantName: "Pizza Place")
|
|
101
|
+
let state = DeliveryAttributes.ContentState(
|
|
102
|
+
driverName: "Alex",
|
|
103
|
+
estimatedDeliveryTime: Date()...Date().addingTimeInterval(1800),
|
|
104
|
+
currentStep: .preparing
|
|
105
|
+
)
|
|
106
|
+
let content = ActivityContent(state: state, staleDate: nil, relevanceScore: 75)
|
|
107
|
+
|
|
108
|
+
do {
|
|
109
|
+
let activity = try Activity.request(
|
|
110
|
+
attributes: attributes,
|
|
111
|
+
content: content,
|
|
112
|
+
pushType: .token
|
|
113
|
+
)
|
|
114
|
+
print("Started activity: \(activity.id)")
|
|
115
|
+
} catch {
|
|
116
|
+
print("Failed to start activity: \(error)")
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Updating
|
|
121
|
+
|
|
122
|
+
Update the dynamic content state from the app. Use `AlertConfiguration` to
|
|
123
|
+
trigger a visible banner and sound alongside the update.
|
|
124
|
+
|
|
125
|
+
```swift
|
|
126
|
+
let updatedState = DeliveryAttributes.ContentState(
|
|
127
|
+
driverName: "Alex",
|
|
128
|
+
estimatedDeliveryTime: Date()...Date().addingTimeInterval(600),
|
|
129
|
+
currentStep: .delivering
|
|
130
|
+
)
|
|
131
|
+
let updatedContent = ActivityContent(
|
|
132
|
+
state: updatedState,
|
|
133
|
+
staleDate: Date().addingTimeInterval(300),
|
|
134
|
+
relevanceScore: 90
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
// Silent update
|
|
138
|
+
await activity.update(updatedContent)
|
|
139
|
+
|
|
140
|
+
// Update with an alert
|
|
141
|
+
await activity.update(updatedContent, alertConfiguration: AlertConfiguration(
|
|
142
|
+
title: "Order Update",
|
|
143
|
+
body: "Your driver is nearby!",
|
|
144
|
+
sound: .default
|
|
145
|
+
))
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Ending
|
|
149
|
+
|
|
150
|
+
End the activity when the tracked event completes. Choose a dismissal policy
|
|
151
|
+
to control how long the ended activity lingers on the Lock Screen.
|
|
152
|
+
|
|
153
|
+
```swift
|
|
154
|
+
let finalState = DeliveryAttributes.ContentState(
|
|
155
|
+
driverName: "Alex",
|
|
156
|
+
estimatedDeliveryTime: Date()...Date(),
|
|
157
|
+
currentStep: .delivered
|
|
158
|
+
)
|
|
159
|
+
let finalContent = ActivityContent(state: finalState, staleDate: nil, relevanceScore: 0)
|
|
160
|
+
|
|
161
|
+
// System decides when to remove (up to 4 hours)
|
|
162
|
+
await activity.end(finalContent, dismissalPolicy: .default)
|
|
163
|
+
|
|
164
|
+
// Remove immediately
|
|
165
|
+
await activity.end(finalContent, dismissalPolicy: .immediate)
|
|
166
|
+
|
|
167
|
+
// Remove after a specific time (max 4 hours from now)
|
|
168
|
+
await activity.end(finalContent, dismissalPolicy: .after(Date().addingTimeInterval(3600)))
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Always end activities on all code paths -- success, error, and cancellation.
|
|
172
|
+
A leaked activity stays on the Lock Screen until the system kills it (up to
|
|
173
|
+
8 hours), which frustrates users.
|
|
174
|
+
|
|
175
|
+
## Lock Screen Presentation
|
|
176
|
+
|
|
177
|
+
The Lock Screen is the primary surface for Live Activities. Every device with
|
|
178
|
+
iOS 16.1+ displays Live Activities here. Design this layout first.
|
|
179
|
+
|
|
180
|
+
```swift
|
|
181
|
+
struct DeliveryActivityWidget: Widget {
|
|
182
|
+
var body: some WidgetConfiguration {
|
|
183
|
+
ActivityConfiguration(for: DeliveryAttributes.self) { context in
|
|
184
|
+
// Lock Screen / StandBy / CarPlay / paired Mac content
|
|
185
|
+
VStack(alignment: .leading, spacing: 8) {
|
|
186
|
+
HStack {
|
|
187
|
+
Text(context.attributes.restaurantName)
|
|
188
|
+
.font(.headline)
|
|
189
|
+
Spacer()
|
|
190
|
+
Text("Order #\(context.attributes.orderNumber)")
|
|
191
|
+
.font(.caption)
|
|
192
|
+
.foregroundStyle(.secondary)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if context.isStale {
|
|
196
|
+
Label("Updating...", systemImage: "arrow.trianglehead.2.clockwise")
|
|
197
|
+
.font(.subheadline)
|
|
198
|
+
.foregroundStyle(.secondary)
|
|
199
|
+
} else {
|
|
200
|
+
HStack {
|
|
201
|
+
Label(context.state.driverName, systemImage: "person.fill")
|
|
202
|
+
Spacer()
|
|
203
|
+
Text(timerInterval: context.state.estimatedDeliveryTime,
|
|
204
|
+
countsDown: true)
|
|
205
|
+
.monospacedDigit()
|
|
206
|
+
}
|
|
207
|
+
.font(.subheadline)
|
|
208
|
+
|
|
209
|
+
// Progress steps
|
|
210
|
+
HStack(spacing: 12) {
|
|
211
|
+
ForEach(DeliveryStep.allCases, id: \.self) { step in
|
|
212
|
+
Image(systemName: step.icon)
|
|
213
|
+
.foregroundStyle(
|
|
214
|
+
step <= context.state.currentStep ? .primary : .tertiary
|
|
215
|
+
)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
.padding()
|
|
221
|
+
} dynamicIsland: { context in
|
|
222
|
+
// Dynamic Island closures (see next section)
|
|
223
|
+
DynamicIsland {
|
|
224
|
+
// Expanded regions...
|
|
225
|
+
DynamicIslandExpandedRegion(.leading) {
|
|
226
|
+
Image(systemName: "box.truck.fill").font(.title2)
|
|
227
|
+
}
|
|
228
|
+
DynamicIslandExpandedRegion(.trailing) {
|
|
229
|
+
Text(timerInterval: context.state.estimatedDeliveryTime,
|
|
230
|
+
countsDown: true)
|
|
231
|
+
.font(.caption).monospacedDigit()
|
|
232
|
+
}
|
|
233
|
+
DynamicIslandExpandedRegion(.center) {
|
|
234
|
+
Text(context.attributes.restaurantName).font(.headline)
|
|
235
|
+
}
|
|
236
|
+
DynamicIslandExpandedRegion(.bottom) {
|
|
237
|
+
HStack(spacing: 12) {
|
|
238
|
+
ForEach(DeliveryStep.allCases, id: \.self) { step in
|
|
239
|
+
Image(systemName: step.icon)
|
|
240
|
+
.foregroundStyle(
|
|
241
|
+
step <= context.state.currentStep ? .primary : .tertiary
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
} compactLeading: {
|
|
247
|
+
Image(systemName: "box.truck.fill")
|
|
248
|
+
} compactTrailing: {
|
|
249
|
+
Text(timerInterval: context.state.estimatedDeliveryTime,
|
|
250
|
+
countsDown: true)
|
|
251
|
+
.frame(width: 40).monospacedDigit()
|
|
252
|
+
} minimal: {
|
|
253
|
+
Image(systemName: "box.truck.fill")
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Lock Screen Sizing
|
|
261
|
+
|
|
262
|
+
The Lock Screen presentation has limited vertical space. Avoid layouts taller
|
|
263
|
+
than roughly 160 points. Use `supplementalActivityFamilies` to opt into
|
|
264
|
+
`.small` (compact) or `.medium` (standard) sizing:
|
|
265
|
+
|
|
266
|
+
```swift
|
|
267
|
+
ActivityConfiguration(for: DeliveryAttributes.self) { context in
|
|
268
|
+
// Lock Screen content
|
|
269
|
+
} dynamicIsland: { context in
|
|
270
|
+
// Dynamic Island
|
|
271
|
+
}
|
|
272
|
+
.supplementalActivityFamilies([.small, .medium])
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Dynamic Island
|
|
276
|
+
|
|
277
|
+
The Dynamic Island is available on iPhone 14 Pro and later. It has three
|
|
278
|
+
presentation modes. Design all three, but treat the Lock Screen as the primary
|
|
279
|
+
surface since not all devices have a Dynamic Island.
|
|
280
|
+
|
|
281
|
+
### Compact (Leading + Trailing)
|
|
282
|
+
|
|
283
|
+
Always visible when a single Live Activity is active. Space is extremely
|
|
284
|
+
limited -- show only the most critical information.
|
|
285
|
+
|
|
286
|
+
| Region | Purpose |
|
|
287
|
+
|---|---|
|
|
288
|
+
| `compactLeading` | Icon or tiny label identifying the activity |
|
|
289
|
+
| `compactTrailing` | One key value (timer, score, status) |
|
|
290
|
+
|
|
291
|
+
### Minimal
|
|
292
|
+
|
|
293
|
+
Shown when multiple Live Activities compete for space. Only one activity gets
|
|
294
|
+
the minimal slot. Display a single icon or glyph.
|
|
295
|
+
|
|
296
|
+
### Expanded Regions
|
|
297
|
+
|
|
298
|
+
Shown when the user long-presses the Dynamic Island.
|
|
299
|
+
|
|
300
|
+
| Region | Position |
|
|
301
|
+
|---|---|
|
|
302
|
+
| `.leading` | Left of the TrueDepth camera; wraps below |
|
|
303
|
+
| `.trailing` | Right of the TrueDepth camera; wraps below |
|
|
304
|
+
| `.center` | Directly below the camera |
|
|
305
|
+
| `.bottom` | Below all other regions |
|
|
306
|
+
|
|
307
|
+
### Keyline Tint
|
|
308
|
+
|
|
309
|
+
Apply a subtle tint to the Dynamic Island border:
|
|
310
|
+
|
|
311
|
+
```swift
|
|
312
|
+
DynamicIsland { /* expanded */ }
|
|
313
|
+
compactLeading: { /* ... */ }
|
|
314
|
+
compactTrailing: { /* ... */ }
|
|
315
|
+
minimal: { /* ... */ }
|
|
316
|
+
.keylineTint(.blue)
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Push-to-Update
|
|
320
|
+
|
|
321
|
+
Push-to-update sends Live Activity updates through APNs, which is more
|
|
322
|
+
efficient than polling from the app and works when the app is suspended.
|
|
323
|
+
|
|
324
|
+
### Setup
|
|
325
|
+
|
|
326
|
+
Pass `.token` as the `pushType` when starting the activity, then forward the
|
|
327
|
+
push token to your server:
|
|
328
|
+
|
|
329
|
+
```swift
|
|
330
|
+
let activity = try Activity.request(
|
|
331
|
+
attributes: attributes,
|
|
332
|
+
content: content,
|
|
333
|
+
pushType: .token
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
// Observe token changes -- tokens can rotate
|
|
337
|
+
Task {
|
|
338
|
+
for await token in activity.pushTokenUpdates {
|
|
339
|
+
let tokenString = token.map { String(format: "%02x", $0) }.joined()
|
|
340
|
+
try await ServerAPI.shared.registerActivityToken(
|
|
341
|
+
tokenString, activityID: activity.id
|
|
342
|
+
)
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### APNs Payload Format
|
|
348
|
+
|
|
349
|
+
Send an HTTP/2 POST to APNs with these headers and JSON body:
|
|
350
|
+
|
|
351
|
+
**Required HTTP headers:**
|
|
352
|
+
- `apns-push-type: liveactivity`
|
|
353
|
+
- `apns-topic: <bundle-id>.push-type.liveactivity`
|
|
354
|
+
- `apns-priority: 5` (low) or `10` (high, triggers alert)
|
|
355
|
+
|
|
356
|
+
**Update payload:**
|
|
357
|
+
|
|
358
|
+
```json
|
|
359
|
+
{
|
|
360
|
+
"aps": {
|
|
361
|
+
"timestamp": 1700000000,
|
|
362
|
+
"event": "update",
|
|
363
|
+
"content-state": {
|
|
364
|
+
"driverName": "Alex",
|
|
365
|
+
"estimatedDeliveryTime": {
|
|
366
|
+
"lowerBound": 1700000000,
|
|
367
|
+
"upperBound": 1700001800
|
|
368
|
+
},
|
|
369
|
+
"currentStep": "delivering"
|
|
370
|
+
},
|
|
371
|
+
"stale-date": 1700000300,
|
|
372
|
+
"alert": {
|
|
373
|
+
"title": "Delivery Update",
|
|
374
|
+
"body": "Your driver is nearby!"
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**End payload:** Same structure with `"event": "end"` and optional `"dismissal-date"`.
|
|
381
|
+
|
|
382
|
+
The `content-state` JSON must match the `ContentState` Codable structure
|
|
383
|
+
exactly. Mismatched keys or types cause silent failures.
|
|
384
|
+
|
|
385
|
+
### Push-to-Start
|
|
386
|
+
|
|
387
|
+
Start a Live Activity remotely without the app running (iOS 17.2+):
|
|
388
|
+
|
|
389
|
+
```swift
|
|
390
|
+
Task {
|
|
391
|
+
for await token in Activity<DeliveryAttributes>.pushToStartTokenUpdates {
|
|
392
|
+
let tokenString = token.map { String(format: "%02x", $0) }.joined()
|
|
393
|
+
try await ServerAPI.shared.registerPushToStartToken(tokenString)
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Frequent Push Updates
|
|
399
|
+
|
|
400
|
+
Add `NSSupportsLiveActivitiesFrequentUpdates = YES` to Info.plist to increase
|
|
401
|
+
the push update budget. Use for activities that update more than once per
|
|
402
|
+
minute (sports scores, ride tracking).
|
|
403
|
+
|
|
404
|
+
## iOS 26 Additions
|
|
405
|
+
|
|
406
|
+
### Scheduled Live Activities (iOS 26+)
|
|
407
|
+
|
|
408
|
+
Schedule a Live Activity to start at a future time. The system starts the
|
|
409
|
+
activity automatically without the app being in the foreground. Use for events
|
|
410
|
+
with known start times (sports games, flights, scheduled deliveries).
|
|
411
|
+
|
|
412
|
+
```swift
|
|
413
|
+
let scheduledDate = Calendar.current.date(
|
|
414
|
+
from: DateComponents(year: 2026, month: 3, day: 15, hour: 19, minute: 0)
|
|
415
|
+
)!
|
|
416
|
+
|
|
417
|
+
let activity = try Activity.request(
|
|
418
|
+
attributes: attributes,
|
|
419
|
+
content: content,
|
|
420
|
+
pushType: .token,
|
|
421
|
+
start: scheduledDate
|
|
422
|
+
)
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### ActivityStyle (iOS 16.1+ type, `style:` parameter iOS 26+)
|
|
426
|
+
|
|
427
|
+
Control persistence: `.standard` (persists until ended, default) or `.transient` (system may dismiss automatically). Use `.transient` for short-lived updates like transit arrivals. The `style:` parameter on `Activity.request` requires iOS 26+.
|
|
428
|
+
|
|
429
|
+
```swift
|
|
430
|
+
let activity = try Activity.request(
|
|
431
|
+
attributes: attributes, content: content,
|
|
432
|
+
pushType: .token, style: .transient
|
|
433
|
+
)
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Paired Mac & CarPlay (iOS 26+)
|
|
437
|
+
|
|
438
|
+
Live Activities automatically appear on a paired Mac running macOS Tahoe and on the CarPlay Home Screen. No additional code needed — ensure Lock Screen layout is legible at smaller scales.
|
|
439
|
+
|
|
440
|
+
### Channel-Based Push (iOS 18+)
|
|
441
|
+
|
|
442
|
+
Broadcast updates to many Live Activities at once with `.channel`:
|
|
443
|
+
|
|
444
|
+
```swift
|
|
445
|
+
let activity = try Activity.request(
|
|
446
|
+
attributes: attributes, content: content,
|
|
447
|
+
pushType: .channel("delivery-updates")
|
|
448
|
+
)
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
## Common Mistakes
|
|
452
|
+
|
|
453
|
+
**DON'T:** Put too much content in the compact presentation -- it is tiny.
|
|
454
|
+
**DO:** Show only the most critical info (icon + one value) in compact leading/trailing.
|
|
455
|
+
|
|
456
|
+
**DON'T:** Update Live Activities too frequently from the app (drains battery).
|
|
457
|
+
**DO:** Use push-to-update for server-driven updates. Limit app-side updates to user actions.
|
|
458
|
+
|
|
459
|
+
**DON'T:** Forget to end the activity when the event completes.
|
|
460
|
+
**DO:** Always end activities on success, error, and cancellation paths. A leaked activity frustrates users.
|
|
461
|
+
|
|
462
|
+
**DON'T:** Assume the Dynamic Island is available (only iPhone 14 Pro+).
|
|
463
|
+
**DO:** Design for the Lock Screen as the primary surface; Dynamic Island is supplementary.
|
|
464
|
+
|
|
465
|
+
**DON'T:** Store sensitive information in ActivityAttributes (visible on Lock Screen).
|
|
466
|
+
**DO:** Keep sensitive data in the app and show only safe-to-display summaries.
|
|
467
|
+
|
|
468
|
+
**DON'T:** Forget to handle stale dates.
|
|
469
|
+
**DO:** Check `context.isStale` in views and show fallback UI ("Updating..." or similar).
|
|
470
|
+
|
|
471
|
+
**DON'T:** Ignore push token rotation. Tokens can change at any time.
|
|
472
|
+
**DO:** Use `activity.pushTokenUpdates` async sequence and re-register on every emission.
|
|
473
|
+
|
|
474
|
+
**DON'T:** Forget the `NSSupportsLiveActivities` Info.plist key.
|
|
475
|
+
**DO:** Add `NSSupportsLiveActivities = YES` to the host app's Info.plist (not the extension).
|
|
476
|
+
|
|
477
|
+
**DON'T:** Use the deprecated `contentState`-based API for request/update/end.
|
|
478
|
+
**DO:** Use `ActivityContent` for all lifecycle calls.
|
|
479
|
+
|
|
480
|
+
**DON'T:** Put heavy logic in Live Activity views. They render in a size-limited widget process.
|
|
481
|
+
**DO:** Pre-compute display values and pass them through `ContentState`.
|
|
482
|
+
|
|
483
|
+
## Review Checklist
|
|
484
|
+
|
|
485
|
+
- [ ] `ActivityAttributes` defines static properties and `ContentState`
|
|
486
|
+
- [ ] `NSSupportsLiveActivities = YES` in host app Info.plist
|
|
487
|
+
- [ ] Activity uses `ActivityContent` (not deprecated contentState API)
|
|
488
|
+
- [ ] Activity ended in all code paths (success, error, cancellation)
|
|
489
|
+
- [ ] Lock Screen layout handles `context.isStale`
|
|
490
|
+
- [ ] Dynamic Island compact, expanded, and minimal implemented
|
|
491
|
+
- [ ] Push token forwarded to server via `activity.pushTokenUpdates`
|
|
492
|
+
- [ ] `AlertConfiguration` used for important updates
|
|
493
|
+
- [ ] `ActivityAuthorizationInfo` checked before starting
|
|
494
|
+
- [ ] ContentState kept small (serialized on every update)
|
|
495
|
+
- [ ] Tested on device (Dynamic Island differs from Simulator)
|
|
496
|
+
- [ ] Ensure ActivityAttributes and ContentState types are Sendable; update Live Activity UI on @MainActor
|
|
497
|
+
|
|
498
|
+
## References
|
|
499
|
+
|
|
500
|
+
- See [references/activitykit-patterns.md](references/activitykit-patterns.md) for patterns and code examples
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
Vendored from: https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/activitykit
|