How does Watch Connectivity work: the transfer types, reachability, and how do you choose between them?

19.6.2 · L5 · Interview

Predict first

Before activation, what does the default session report?

import WatchConnectivity

print(WCSession.isSupported())
let s = WCSession.default
print(s.activationState.rawValue, s.isReachable, s.isPaired, WCSessionActivationState.activated.rawValue)
  • true, then 0 false false 2
  • false, then 2 true true 0
  • true, then 2 true true 2

Mental model. Watch Connectivity is a courier with four services: a phone call (interactive message, only works if the other side picks up), a noticeboard that always shows the latest notice (application context), registered mail delivered in order (user info) and a parcel service (files).

Watch Connectivity (WCSession) is the framework for an iPhone app and its paired watch app to exchange data. Both sides activate the singleton WCSession.default early (set the delegate, then activate(); check WCSession.isSupported() first, true on iPhone and watch but not iPad), and the state starts as notActivated (0) until activation completes (activated is 2); until then isReachable and isPaired are false. There are four transfer types with different guarantees, and choosing right is the whole skill. Interactive messages (sendMessage(_:replyHandler:errorHandler:), and sendMessageData) are immediate, two-way and require the counterpart to be reachable (the other app is active or the watch is within range and the app running): they fail with an error otherwise, so use them only for live interaction, never for reliable delivery. Application context (updateApplicationContext(_:)) sends a latest-state dictionary: only the most recent value is kept (older unsent ones are replaced), delivered when possible even if the receiver is not running, ideal for settings and “current state” such as the user’s signed-in status or a theme. User info transfer (transferUserInfo(_:)) is a queued, reliable, in-order delivery of dictionaries: every one is delivered (even after the app restarts), which suits events that must not be lost, such as a workout completion or a to-do edit. File transfer (transferFile(_:metadata:)) sends a file in the background with metadata, for larger data; there is also transferCurrentComplicationUserInfo, a high-priority user info for complication updates with a small daily allowance (about 50 a day).

Design guidance. Prefer an independent watch app that talks to your server directly, and use Watch Connectivity for settings and handoff, since the pairing can be slow, unavailable or absent (a family-setup watch has no paired iPhone). Treat messages as unreliable and the queue-based transfers as eventually consistent: version your payloads, make handling idempotent, and tolerate delivery after long delays or out of the sender’s current state. Payloads are property-list types only and must stay small. Handle the session lifecycle on iPhone (sessionDidBecomeInactive and sessionDidDeactivate when the user switches watches: re-activate the session). Do not use it for heavy sync: put large data on the server and send a signal or a token. Test with real devices (the simulator pair is limited, and background delivery timing differs), toggle airplane mode and Bluetooth, and log the delegate callbacks, since a common failure is calling sendMessage while isReachable is false. Use outstandingUserInfoTransfers and outstandingFileTransfers to inspect the queue and cancel stale items. For data that both apps need, a shared server or CloudKit, with Watch Connectivity as an accelerator, is more robust than relying on it as the only channel.

An unactivated session reports notActivated (0), is not reachable and not paired; activated is value 2.

DeliveryBest for
sendMessageimmediate, both ways, only if reachablelive interaction while both are active
updateApplicationContextlatest value only, delivered when possiblesettings and current state
transferUserInfoqueued, in order, every item deliveredevents that must not be lost
transferFilebackground file with metadatalarger data such as a recording

Common traps

  • Using sendMessage for data that must arrive. It fails when the other side is not reachable; use user info or application context.
  • Sending before the session is activated. The state is notActivated and nothing is delivered; wait for activation to complete.

They might follow up with

  • Which transfer keeps only the latest value? Application context.
  • Which guarantees ordered, reliable delivery of every item? transferUserInfo.

Related questions

  • 19.6.1 How is a watchOS app structured today versus the legacy WatchKit app and extension, and what do independent…
  • 19.6.3 How have watch complications moved from ClockKit to WidgetKit, and what are accessory families and the Smart…
  • 19.1.2 How do app groups, shared containers and keychain access groups let an app and its extensions share data, and…

← How is a watchOS app structured today versus the legacy WatchKit app…   How have watch complications moved from ClockKit to WidgetKit, and… →