watchOS 开发入门:独立应用与复杂功能

FreeGuideOnline 最新 2026-06-17

watchOS 开发入门:独立应用与复杂功能

watchOS 开发正在经历一场变革——从 iPhone 的“附属品”到完全独立的 Apple Watch 应用。本篇教程将带你从零开始,掌握 watchOS 独立应用的创建、界面构建以及最具代表性的复杂功能开发。无论你是经验丰富的 iOS 开发者还是初次接触苹果生态,都能通过本文学会如何在手腕上构建完整的体验。


什么是 watchOS 独立应用?

过去,watchOS 应用必须依赖 iPhone 应用才能存在,用户需要先安装对应的 iOS 版。独立应用(Standalone) 则完全摆脱了这一束缚。它可以直接在 App Store 上架,无需配套 iOS 应用,用户可以仅通过 Apple Watch 完成下载、安装和使用。

独立应用带来的主要变化:

  • 独立的目标(Target),工程中不再强制包含 iOS 应用。
  • 所有代码和资源都仅存在于 Watch App 内,没有 iPhone 端的扩展。
  • 可以使用 Watch 的完整能力:网络请求、健康数据、后台任务等。
  • 应用生命周期完全由系统管理,没有伴侣应用的干扰。

本教程将聚焦于独立应用的开发,并在此基础上加入“复杂功能”这一 watchOS 的核心亮点。


开发环境准备

  • Xcode 15 或更高版本(推荐使用最新正式版)
  • macOS Ventura 或更高版本
  • 一个 Apple Developer 账号(用于真机调试,模拟器不需要)
  • 基础 Swift 和 SwiftUI 知识

创建项目时选择 watchOS > App 模板。在选项界面中,务必勾选 “Include Complication”,这将自动为我们生成复杂功能所需的基础文件。

项目结构将包含以下关键部分:

  • YourAppNameApp.swift:应用入口
  • ContentView.swift:主界面
  • ComplicationController.swift:复杂功能的控制器
  • Assets.xcassets:资源文件

创建你的第一个 watchOS 独立应用

理解 App 结构和生命周期

YourAppNameApp.swift 是应用的启动点:

import SwiftUI

@main
struct YourAppNameApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

这是标准的 SwiftUI 应用结构。watchOS 独立应用同样只有一个 WindowGroup 作为根视图。与 iOS 不同,这里不需要 AppDelegateSceneDelegate,所有生命周期管理都通过 SwiftUI 的修饰器和环境值完成。

设计界面

基于 SwiftUI 构建界面非常直观。下面是一个简单的列表视图,展示了几项健身数据:

struct ContentView: View {
    var body: some View {
        List {
            Label("今日步数 8,642", systemImage: "figure.walk")
            Label("心率 72 bpm", systemImage: "heart.fill")
            Label("活动 450 kcal", systemImage: "flame.fill")
        }
    }
}

利用 ListVStackHStack 等容器,搭配 LabelTextImage 即可快速布局。数字表冠(Digital Crown)和触觉反馈也能通过 .focusable().digitalCrownRotation() 等修饰符实现。

运行与调试

在 Xcode 顶部目标设备选择器中,选择一个 Watch 模拟器(如 Apple Watch Series 9)或配对的真实设备。由于是独立应用,不需要担心 iPhone 的状态,直接点击运行即可。


深入 watchOS 复杂功能(Complications)

复杂功能是用户直接在表盘上看到的信息块,也是 watchOS 区别于其他平台的核心交互。通过提供及时、一目了然的数据,你的应用能够成为用户表盘的一部分,极大提高使用频率。

复杂功能的数据模型与提供者

所有复杂功能都由 CLKComplicationDataSource 协议驱动,在项目模板中,你会看到 ComplicationController.swift 里已经实现了该协议。

核心方法 getTimelineEntries 负责提供时间线上的条目:

func getTimelineEntries(for complication: CLKComplication,
                        after date: Date,
                        limit: Int,
                        withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
    // 生成最多 limit 个未来的条目
    var entries: [CLKComplicationTimelineEntry] = []
    for i in 0..<limit {
        guard let futureDate = Calendar.current.date(byAdding: .minute, value: i * 15, to: date) else { continue }
        let template = createTemplate(for: complication.family, date: futureDate)
        let entry = CLKComplicationTimelineEntry(date: futureDate, complicationTemplate: template)
        entries.append(entry)
    }
    handler(entries)
}

每个条目包含一个日期和一个 CLKComplicationTemplate,后者依据不同的复杂功能家族来构建。

配置和支持的家族(Families)

getComplicationDescriptors 中声明你的应用支持哪些表盘样式:

func getComplicationDescriptors(handler: @escaping ([CLKComplicationDescriptor]) -> Void) {
    let descriptors = [
        CLKComplicationDescriptor(identifier: "stepCount",
                                  displayName: "今日步数",
                                  supportedFamilies: [.modularSmall, .utilitarianLarge, .graphicCircular])
    ]
    handler(descriptors)
}

常用家族及其特点:

家族 样式 适用内容
.modularSmall 模块小圆形 单个数值或短文本
.utilitarianLarge 实用大矩形 详细文字、进度
.graphicCircular 图文全圆环 图形化显示,如进度环
.graphicCorner 图文边角 复杂组合视图

根据不同的家族,createTemplate 方法会构建对应的模板。例如,为 .modularSmall 创建显示步数的模板:

private func createTemplate(for family: CLKComplicationFamily, date: Date) -> CLKComplicationTemplate {
    switch family {
    case .modularSmall:
        let template = CLKComplicationTemplateModularSmallStackText()
        template.line1TextProvider = CLKSimpleTextProvider(text: "8423")
        template.line2TextProvider = CLKSimpleTextProvider(text: "步")
        return template
    // 处理其他家族...
    default:
        return CLKComplicationTemplate()
    }
}

占位符与模板文本

当用户浏览表盘复杂功能列表时,系统会调用 getPlaceholderTemplate 来显示一个静态预览。该预览应简明展示你的功能:

func getPlaceholderTemplate(for complication: CLKComplication,
                            withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
    let template = CLKComplicationTemplateModularSmallStackText()
    template.line1TextProvider = CLKSimpleTextProvider(text: "----")
    template.line2TextProvider = CLKSimpleTextProvider(text: "步")
    handler(template)
}

时间线更新与刷新策略

独立应用可以通过后台任务或来自服务器的推送通知来刷新复杂功能数据。调用 CLKComplicationServer.sharedInstance().reloadTimeline(for:) 即可触发更新。在 ComplicationController 中重写 getNextRequestedUpdateDate 可以定义下次唤醒时间:

func getNextRequestedUpdateDate(handler: @escaping (Date?) -> Void) {
    // 请求每半小时刷新一次
    handler(Date().addingTimeInterval(30 * 60))
}

对于实时性要求不高的数据,这样做既省电又能保证数据相对新鲜。


独立应用的特殊考量

网络请求

独立应用可以直接发起 URLSession 请求,无需经过 iPhone。但要注意:

  • 默认只允许 HTTPS,必须在 Info.plist 中显式声明所需的域名(App Transport Security)。
  • 后台请求需使用 URLSessionConfiguration.background 配置。

健康与传感器数据

要在独立应用中读取健康数据,必须开启 HealthKit 能力(Capabilities),并在 Watch 上单独请求权限。由于没有 iPhone 转发,所有传感器(心率、加速度计等)的访问均由 Watch 自身完成。

后台任务

watchOS 后台执行比 iOS 严格许多。使用 WKApplicationRefreshBackgroundTask 只能获得有限的刷新机会。建议结合时间线更新和通知来保持数据存活。


总结与后续学习

通过本教程,你已掌握 watchOS 独立应用从创建到提供复杂功能的完整流程。关键要点:

  • 独立应用带来完全自主的 Watch 体验,工程模板选择 watchOS App 即可。
  • 复杂功能通过 CLKComplicationDataSource 向表盘提供时间线条目,支持多种家族。
  • 实际开发中需平衡数据新鲜度与功耗。

下一步,你可以深入探索:

  • 为复杂功能添加点击交互(通过 tapAction 打开应用特定视图)
  • 实现更图形化的模板,如 graphicRectangulargraphicExtraLarge
  • 使用 WidgetKit 风格的“复杂功能建议”(watchOS 10+ 的新 API)
  • 结合 Swift Charts 在表盘上呈现迷你图表

现在,打开 Xcode,开始打造你的第一款腕上应用吧!