Sample CodeiOS, iPadOS, Mac Catalyst, watchOSReviewed 2026-07-21View on Apple Developer

Transferring data with Watch Connectivity

At a glance

Item Summary
Purpose Transfer data between a watchOS app and its companion iOS app.
App architecture A Swift sample bundle with entry-bearing project variants SimpleWatchConnectivity Watch App, SimpleWatchConnectivity, SimpleWatchWidget, each leading to WatchConnectivity APIs.
Main patterns View-controller organization, Protocol-oriented abstraction, Delegate or data-source callbacks, Binding-based state propagation
Project style 20 scanned source file(s) across Swift, organized around ranked entry, type, and file boundaries.

Project structure

Source bundle/
├── SimpleWatchConnectivity Watch App/
│   ├── SimpleWatchConnectivityWatchApp.swift
│   ├── AppDelegate.swift
│   ├── CommandView.swift
│   ├── ContentView.swift
│   ├── FileTransfersView.swift
│   └── UserInfoTransfersView.swift
├── SimpleWatchWidget/
│   └── SimpleWatchWidget.swift
├── SimpleWatchConnectivity/
│   ├── AppDelegate.swift
│   ├── CommandsViewController.swift
│   └── FileTransfersViewController.swift
└── Shared/
    ├── TestDataProvider.swift
    └── CommandStatus.swift

Structure observations

  • Architecturally prominent files are ranked from entry points and role-named declarations; resource-only paths are omitted.
  • Primary languages: Swift.
  • The verified tree contains 11 project/configuration file(s) and 28 source declaration(s).

Overall architecture

Reference code

SimpleWatchConnectivity Watch App/SimpleWatchConnectivityWatchApp.swift:10 — architecture anchor

@main
struct SimpleWatchConnectivityWatchApp: App {
    // ...
}

Interpretation

The branches represent separate entry-bearing project variants in the downloaded bundle, not runtime calls between those variants. Each branch is intentionally collapsed at the documented framework boundary; the detailed target-local flow remains in the cited files. Ownership is claimed only where the next section cites a stored property or assignment.

Ownership and state

Ownership evidence

SimpleWatchConnectivity Watch App/SimpleWatchConnectivityWatchApp.swift:12 — stored dependency or nearest verified ownership anchor

    @WKApplicationDelegateAdaptor var appDelegate: AppDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
Owner Object or state Relationship Mutation authority
SimpleWatchConnectivityWatchApp AppDelegate (appDelegate) stores or receives App/module collaborators
SimpleEntry Date (date) owns value state Initialized by the owner; the binding is immutable
SimpleEntry String (timestamp) owns value state Initialized by the owner; the binding is immutable
SimpleEntry UIColor (color) stores or receives Initialized by the owner; the binding is immutable

Composition arrows indicate a source-visible construction expression or locally owned value state; aggregation means the owner stores or receives a dependency without proving exclusive lifetime ownership.

Class and protocol design

Shared/TestDataProvider.swift:23 — representative type boundary

protocol TestDataProvider {
    // ...
}
Type Responsibility Depends on or conforms to
SimpleWatchConnectivityWatchApp Application entry and top-level composition App
AppDelegate Receives callback-driven events UIResponder, UIApplicationDelegate
TestDataProvider Defines a capability or collaboration contract Concrete collaborators/imported frameworks
Provider Supplies a capability or framework resource TimelineProvider
SimpleWatchWidgetEntryView User-interface presentation and input forwarding View
Command Represents or runs a user/system command String
AppDelegate Receives callback-driven events NSObject, WKApplicationDelegate
CommandView User-interface presentation and input forwarding View, TestDataProvider, SessionCommands
ContentView User-interface presentation and input forwarding View
FileTransfersView User-interface presentation and input forwarding View

The source explicitly defines local protocol relationships: CommandViewTestDataProvider, CommandViewSessionCommands, CommandsViewControllerTestDataProvider, CommandsViewControllerSessionCommands, WCSessionUserInfoTransferSessionTransfer, WCSessionFileTransferSessionTransfer.

Access control

Symbol Access Verified effect Likely rationale
fileTransferObervations (Shared/FileTransferObservers.swift:17) private Use is restricted to the lexical declaration and same-file extensions allowed by Swift. Inference: keep state mutation or dependency lifetime inside the owning implementation.
progresssDescriptions (Shared/FileTransferObservers.swift:18) private(set) Read access follows the declaration; writes remain in the private scope. Inference: allow observation while reserving invariant-changing writes for the owner.
observations (Shared/FileTransferObservers.swift:20) private Use is restricted to the lexical declaration and same-file extensions allowed by Swift. Inference: keep state mutation or dependency lifetime inside the owning implementation.
fileHandle (Shared/Logger.swift:16) private Use is restricted to the lexical declaration and same-file extensions allowed by Swift. Inference: keep state mutation or dependency lifetime inside the owning implementation.

Reference code

Shared/FileTransferObservers.swift:17 — representative boundary

    private var fileTransferObervations = [WCSessionFileTransfer: NSKeyValueObservation]()
    private(set) var progresssDescriptions = [WCSessionFileTransfer: String]()

    private var observations: [NSKeyValueObservation] {
        return Array(fileTransferObervations.values)
    }

Swift declarations without a modifier are internal; explicit private, fileprivate, private(set), public, or open entries above are interpreted by language semantics. Objective-C/C samples instead rely on header and implementation boundaries, which are not equivalent to Swift lexical privacy.

Logic ownership and placement

Logic Owning type or file Placement rationale
Application entry and top-level composition SimpleWatchConnectivityWatchApp The source’s App suffix makes this role explicit.
Represents or runs a user/system command Command The source’s Command suffix makes this role explicit.
View lifecycle, callbacks, and feature coordination CommandsViewController, FileTransfersViewController, MainViewController, UserInfoTransfersViewController The source’s Controller suffix makes this role explicit.
Receives callback-driven events AppDelegate The source’s Delegate suffix makes this role explicit.
Supplies a capability or framework resource Provider, TestDataProvider The source’s Provider suffix makes this role explicit.
User-interface presentation and input forwarding CommandView, ContentView, FileTransfersView, SimpleWatchWidgetEntryView The source’s View suffix makes this role explicit.

Design patterns

Pattern Source evidence Purpose or tradeoff
View-controller organization SimpleWatchConnectivity/CommandsViewController.swift:11 A controller is the verified coordination boundary; this is MVC-style only where a separate model is present.
Protocol-oriented abstraction SimpleWatchConnectivity Watch App/CommandView.swift:18 A local protocol and concrete conformance create an explicit capability boundary.
Delegate or data-source callbacks Shared/SessionDelegator.swift:24 Callback protocols invert event delivery back into the sample’s owner.
Binding-based state propagation SimpleWatchConnectivity Watch App/CommandView.swift:25 A binding exposes controlled read/write access while the upstream owner remains authoritative.

Main application flow

A reply-bearing message crosses the local command surface, Watch Connectivity, the peer delegate, and main-queue notifications on both devices.

Reference code

Shared/SessionCommands.swift:47 — the sender publishes both the initial sent state and the asynchronous reply or error state.

func sendMessage(_ message: [String: Any]) {
    var commandStatus = CommandStatus(command: .sendMessage, phrase: .sent)
    commandStatus.timedColor = TimedColor(message)
    guard WCSession.default.activationState == .activated else {
        return handleSessionUnactivated(with: commandStatus)
    }
    WCSession.default.sendMessage(message, replyHandler: { replyMessage in
        commandStatus.phrase = .replied
        commandStatus.timedColor = TimedColor(replyMessage)
        self.postNotificationOnMainQueueAsync(name: .dataDidFlow, object: commandStatus)
    }, errorHandler: { error in
        commandStatus.phrase = .failed
        commandStatus.errorMessage = error.localizedDescription
        self.postNotificationOnMainQueueAsync(name: .dataDidFlow, object: commandStatus)
    })
    postNotificationOnMainQueueAsync(name: .dataDidFlow, object: commandStatus)
}

Shared/SessionDelegator.swift:48 — the receiver records the message and echoes it through the supplied reply callback.

func session(_ session: WCSession, didReceiveMessage message: [String: Any]) {
    var commandStatus = CommandStatus(command: .sendMessage, phrase: .received)
    commandStatus.timedColor = TimedColor(message)
    postNotificationOnMainQueueAsync(name: .dataDidFlow, object: commandStatus)
}

func session(_ session: WCSession, didReceiveMessage message: [String: Any], replyHandler: @escaping ([String: Any]) -> Void) {
    self.session(session, didReceiveMessage: message)
    replyHandler(message)
}

Naming conventions

  • Types: App: SimpleWatchConnectivityWatchApp; Command: Command; Controller: CommandsViewController, FileTransfersViewController, MainViewController, UserInfoTransfersViewController; Delegate: AppDelegate; Provider: Provider, TestDataProvider; View: CommandView, ContentView, FileTransfersView, SimpleWatchWidgetEntryView, UserInfoTransfersView.
  • Protocols: TestDataProvider, SessionCommands, SessionTransfer.
  • Methods: placeholder, getSnapshot, getTimeline, application, timedColor, completeBackgroundTasks, handle, outstandingTransferCount.
  • Files: SimpleWatchConnectivity Watch App/SimpleWatchConnectivityWatchApp.swift, SimpleWatchWidget/SimpleWatchWidget.swift, SimpleWatchConnectivity/AppDelegate.swift, Shared/TestDataProvider.swift, Shared/CommandStatus.swift, SimpleWatchConnectivity Watch App/AppDelegate.swift.

Architecture takeaways

  • SimpleWatchConnectivityWatchApp is the main source-visible entry or composition anchor for this sample.
  • Framework work reaches WatchConnectivity, UIKit, SwiftUI, WidgetKit through a deliberately small high-level chain; the detailed API graph remains inside the cited implementation files.
  • Stored-property evidence identifies lifecycle collaboration; it does not by itself prove exclusive object ownership.
  • Access-control conclusions separate verified language visibility from the likely design rationale.
  • Local protocol relationships provide an explicit substitution boundary.

Source map

Source file Relevant symbols
SimpleWatchConnectivity Watch App/SimpleWatchConnectivityWatchApp.swift SimpleWatchConnectivityWatchApp
SimpleWatchWidget/SimpleWatchWidget.swift Provider, SimpleEntry, SimpleWatchWidgetEntryView, SimpleWatchWidget
SimpleWatchConnectivity/AppDelegate.swift AppDelegate
Shared/TestDataProvider.swift PayloadKey, TestDataProvider
Shared/CommandStatus.swift Command, Phrase, TimedColor, CommandStatus
SimpleWatchConnectivity Watch App/AppDelegate.swift AppDelegate
SimpleWatchConnectivity Watch App/CommandView.swift CommandView
SimpleWatchConnectivity Watch App/ContentView.swift ContentView
SimpleWatchConnectivity Watch App/FileTransfersView.swift FileTransfersView
SimpleWatchConnectivity Watch App/UserInfoTransfersView.swift UserInfoTransfersView
Shared/SessionCommands.swift SessionCommands, asynchronous reply and transfer commands
Shared/SessionDelegator.swift SessionDelegator, WCSessionDelegate callbacks