watchos-development
watchOS Development
Section titled “watchOS Development”Guidance for building watchOS apps that behave the way the platform expects: independent by default, SwiftUI-first, glanceable, and resilient to a paired iPhone that may not be nearby.
Agent behavior contract (follow these rules)
Section titled “Agent behavior contract (follow these rules)”- Determine the project’s shape before proposing changes: watch-only, paired companion, or independent+companion. Default recommendation for new work is independent + companion — it’s the only shape that degrades gracefully on Family Setup watches and unpaired watches.
- Never let Watch Connectivity become the primary data path. It is an opportunistic optimization on top of a network/CloudKit fetch, not a substitute for one — see
references/watch-connectivity.md. - Default new app entry points to the SwiftUI
Appprotocol (@main,WindowGroup,NavigationStack) — seereferences/platform-basics.mdfor entry-point structure andreferences/design-for-watchos.mdfor how these primitives handle watchOS-specific navigation. Only add aWKApplicationDelegatevia@WKApplicationDelegateAdaptorfor the specific callbacks SwiftUI doesn’t expose (workout recovery, Now Playing, extended runtime, remote-notification registration) — never as a precaution. - Route all networking through
URLSession. Low-level networking (NWConnection, raw sockets,URLSessionStreamTask/WebSocketTask) is blocked by the OS on watchOS except for audio-streaming, VoIP+CallKit, and tvOS-pairing apps — seereferences/background-and-networking.md. - Every
WKRefreshBackgroundTask(includingWKWatchConnectivityRefreshBackgroundTaskandWKURLSessionRefreshBackgroundTask) must reachsetTaskCompletedWithSnapshot(_:)exactly once. Missing this drains the background budget and produces a delayedSIGKILLthat looks unrelated to its cause. - When migrating ClockKit complications to WidgetKit, insist on migrating every complication in the same release. The instant one WidgetKit complication is offered, the system stops calling ClockKit entirely — a partial migration silently breaks the rest on every user’s device.
- For SwiftUI content, only cover what’s genuinely different on watchOS (navigation primitives, toolbar placement, Always On, containerBackground). General SwiftUI state management, layout, and animation belong to the
swiftui-expert-skillandswiftui-liquid-glassskills — don’t re-explain those here. - For workouts and HealthKit specifics (HKWorkoutSession, HKLiveWorkoutBuilder, recovery), defer to the
healthkitskill; this skill only covers how workout data affects Smart Stack suggestions.
First 60 seconds (triage template)
Section titled “First 60 seconds (triage template)”- Clarify the goal: new feature, crash/bugfix, design review, or WatchKit/ClockKit migration?
- Collect minimal facts:
- Project shape (watch-only / paired companion / independent+companion) and whether it’s SwiftUI or still has storyboards
- Deployment target and whether the watchOS 26 SDK / ARM64 submission gate (April 2026) applies
- Is a paired iPhone assumed to be reachable, or must the app work standalone?
- Exact crash signature or error, if debugging
- Branch immediately:
- Background wake crash (
SIGKILLafter a refresh) → background-task completion audit —references/background-and-networking.mdand/orreferences/watch-connectivity.md - Complication/widget not updating → check for a partial ClockKit→WidgetKit migration first —
references/modernization.md - Data not arriving on watch → check Watch Connectivity is not the only path —
references/watch-connectivity.md - Navigation/layout looks wrong → check the navigation primitive matches the content shape —
references/design-for-watchos.md
- Background wake crash (
Routing map (pick the right reference fast)
Section titled “Routing map (pick the right reference fast)”- App structure, independent apps, entry point, Info.plist keys, submission requirements, Foundation Models on watch →
references/platform-basics.md - Navigation (
TabView/NavigationSplitView/NavigationStack), toolbar placement,containerBackground, Always On design →references/design-for-watchos.md - Complications, Smart Stack widgets, RelevanceKit, configurable widgets, APNs widget push →
references/smart-stack-and-complications.md - Controls (Control Center / Action button / Double Tap), Live Activities on watch →
references/controls-and-live-activities.md WCSession, paired-device data transfer, Family Setup, background-task completion for WC wakes →references/watch-connectivity.md- Background tasks,
BGTaskScheduler, URLSession background transfers, TN3135 networking limits →references/background-and-networking.md - WatchKit storyboards → SwiftUI, dual-target → single-target, ClockKit → WidgetKit, watch-only → +companion →
references/modernization.md
Common symptoms → next best move
Section titled “Common symptoms → next best move”EXC_CRASH (SIGKILL)shortly after a background wake →references/background-and-networking.mdand/orreferences/watch-connectivity.md(audit everyWKRefreshBackgroundTaskbranch for a missing completion call)NWConnectionstuck in.waitingwithENETDOWN, works fine in the simulator →references/background-and-networking.md(low-level networking is policy-blocked on device; switch toURLSession)- ClockKit complications silently stop updating after a release →
references/modernization.md(a WidgetKit complication was shipped without migrating the rest) - App shows empty/stale data on Family Setup or an unpaired watch →
references/watch-connectivity.md+references/platform-basics.md(Watch Connectivity was used as the primary path instead of URLSession/CloudKit) - Control doesn’t appear in the watch controls gallery →
references/controls-and-live-activities.md(its intent likely foregrounds the iPhone app — watch placement filters those out) - Two Smart Stack cards for the same event →
references/smart-stack-and-complications.md(missingassociatedKind(_:)between a timeline and a relevant widget) - Tabs never activate, or
NavigationSplitViewdetail selection is stuck →references/design-for-watchos.md(ListunwrapsOptionalselection,TabViewdoesn’t) 'BGTaskScheduler' is unavailable in watchOScompile error →references/background-and-networking.md(needs the Xcode 27 SDK, even though the API is annotated back to watchOS 26)
Reference files
Section titled “Reference files”references/platform-basics.mdreferences/design-for-watchos.mdreferences/smart-stack-and-complications.mdreferences/controls-and-live-activities.mdreferences/watch-connectivity.mdreferences/background-and-networking.mdreferences/modernization.md
Source: CharlesWiltgen/Axiom (axiom-watchos discipline skill), adapted — not copied verbatim.