第1 章 创建WatchKit 项目 第2 章 剖析watchOS 应用 第3 章 实现导航 第4 章 探索控件 第 I 部分 入 门 Apple 经常将Watch 应用当作独立的实体:它等同于iOS 应用的缩小版本,可以独立于 iPhone、iPad 或iPod touch 而存在。虽然Watch 应用正在变得越来越独立,但创建watchOS 应用仍需创建新的iOS 项目并提供一些额外功能。 1.1 终身陪伴 最初的第三方WatchKit 应用要求对运行在iOS 设备上的iOS 应用进行相应的扩展。在 Watch 上运行用户界面时,该扩展充当应用的“大脑”。而在watchOS 2 中,虽然这种分离特 性仍然存在,但扩展和用户界面都运行在Watch 上。因此,为创建Watch 应用,需要在Xcode 中创建新的iOS 项目,并向其添加相应的watchOS 对象。 注意: 第2 章将更详细地介绍watchOS 应用的分离特性,以便更好地理解使用watchOS 应用的 含义。但目前的主要任务是尽快获取并运行一个watchOS 应用,所以暂时忽略一些细节。 (1) 打开Xcode,从主菜单依序选择File | New | Project,创建一个新的iOS 项目。 (2) 在项目模板选择器(如图1-1 所示)中,导航到watchOS Application 类别,选择iOS App with WatchKit App 模板,并单击Next 按钮。 第1章 创建WatchKit 项目 第Ⅰ部分 入 门 4 图1-1 WatchKit App 对象模板 (3) 为项目指定一个名称(此时使用名称HelloWrist),然后从Language 菜单中选择Swift, 并选择Universal 作为Devices 类型,如图1-2 所示。 图1-2 WatchKit App 对象选项 (4) 确保选中了Include Notification Scene、Include Glance Scene 以及Include Complication 选项,并单击Next 按钮。 (5) 选择保存项目的位置,然后单击Create 按钮,完成项目的创建。 第1 章 创建WatchKit 项目 5 项目创建完毕后,将在File Navigator 中看到类似于标准iOS 项目的文件项,但多了许多 额外项,此外对象列表和方案列表也有所不同。第2 章将详细介绍这些新项目的含义。 1.2 向WatchKit App 中添加代码 现在,我们已经创建了一个可以很容易运行的应用;此时,如果你愿意,可以跳到1.3.2 节“尝试HelloWrist!”运行该程序。然而,如果这么做了你可能会有点失望,因为默认模板 并没有包含太多功能。相反,如果向Xcode 创建的一些模板文件中添加额外代码,则可以更 多地展示Watch 的功能。 1.2.1 更新Watch 界面 WatchKit App 的主界面被定义为故事板(storyboard)文件中的一个场景。WatchKit 拥有自 己的UI 组件选项,但这些组件只能在有限的界面上工作,接下来介绍使用这些组件能够完 成哪些工作。 (1) 在Xcode File Navigator 中,展开HelloWrist WatchKit App 文件夹,并单击Interface. storyboard 文件,在Interface Builder 的Storyboard 编辑器中打开WatchKit App 用户界面。 故事板文件加载完毕后,将显示4 个场景,如图1-3 所示。 图1-3 WatchKit App 的Interface.storyboard 文件 (2) 选择Interface Controller Scene 选项。 第Ⅰ部分 入 门 6 (3) 在Object Library 中搜索名为Label(或WKInterfaceLabel)的用户界面元素,如图1-4 所示。 该用户界面元素等同于完整的iOS 应用中的UILabel,但稍后会看到,相对于UILabel, 该元素在功能上存在一定的限制。 注意: Label 元素使用了底层的WKInterfaceLabel 类。如果想要了解任何用户界面元素的更多 信息,可以在Object Library 中单击对应元素,将会显示一个带有更多信息(包括类名)的弹 出框。 (4) 将Label 元素从Object Library 拖放至界面控制器场景上,如图1-5 所示。 图1-4 Object Library 中的WatchKit Label 元素 图1-5 刚放置的Label 元素 (5) 使用Attribute 检查器对该元素的样式进行所需的设置。 图1-6 显示了WatchKit Label 元素所有可用的自定义选项。这里选择将该标签水平居中 放置,如图1-7 所示。 图1-6 Label 元素的自定义选项 图1-7 自定义的Label 元素 第1 章 创建WatchKit 项目 7 注意: 与常规的iOS 故事板不同,此时不能将标签放置在任何所选择的地方,这是因为WatchKit 使用了流布局系统,而在该系统中,元素按照应该出现的顺序放置。第5 章将详细介绍流布 局系统。 1.2.2 编写Watch App 代码 到目前为止已经对“Hello Wrist!”程序进行了简要介绍。再次强调一下,如果想要马上 运行该程序,可以直接跳到1.3.2 节“尝试HelloWrist!”,但在运行之前,还需添加一些更多 的交互。 与UIKit 应用一样,WatchKit 依赖一个按钮用户界面元素来提供许多交互功能。 (1) 在Object Library 中搜索Button(或WKInterfaceButton)元素,如图1-8 所示,并将其 拖放至界面控制器场景中。 图1-8 WatchKit Button 或WKInterfaceButton 元素 由于使用了流布局系统,图1-9 突出显示了不能在界面上对Button 元素进行绝对定位, 而只能相对于现有的Label 元素进行放置。可使用Attribute 检查器对按钮的样式进行设置; 此时将Button 标题设置为Say Hello。 图1-9 将Button 元素拖放至Label 元素之后 第Ⅰ部分 入 门 8 为了让按钮完成一些有用的操作,需要将其挂钩到一个操作方法上;该过程与使用 常规的iOS 故事板完成挂钩操作是相同的。而创建相关操作最简单的方法是启用助理编 辑器(assistant editor),该编辑器可以显示来自HelloWrist WatchKit Extension 文件夹的 InterfaceController.swift 文件。 (2) 按住Ctrl 键并点击新按钮,然后将其拖放到助理编辑器中。当Xcode 显示一条插入 线以及文本“Insert Outlet or Action”(如图1-10 所示)时,释放拖动操作。 图1-10 插入saySomething 操作 (3) 在出现的弹出框中,选择Action 作为Connection 类型,并命名为saySomething。 此时的目的是使Label 元素变为空并通过单击按钮进行填充。 (4) 选择故事板中的标签,并在Attribute 检查器中将其Text 特性更改为空。 如果想要以编程方式更改标签文本,该标签必须拥有一个可从InterfaceController 类访问 的Outlet。 (5) 按住Ctrl 键并点击该标签,然后将其拖放至助理编辑器中,当Xcode 显示插入线时 释放拖动操纵。 (6) 此时,选择Outlet 作为Connection 类型,并将其命名为messageLabel。请按照下面 所示的代码更新saySomething 方法: @IBAction func saySomething() { 第1 章 创建WatchKit 项目 9 messageLabel.setText("Hello Wrist!") } 既然可以更改标签文本,那么接下来让我们实现通过点击按钮在“Hello Wrist”和“Bye Wrist”之间切换文本。 (7) 添加一个名为button 的Outlet,以便以编程方式更改按钮文本。如果想要通过点击按 钮切换标签文本,最简单的方法是检查当前文本值并进行相应的更改。 (8) 用下面所示的代码替换saySomething 方法: @IBAction func saySomething() { if messageLabel.text == "Hello Wrist!" { messageLabel.setText("Bye Wrist!") } else { messageLabel.setText("Hello Wrist!") } } 该代码突出显示了常规的UIKit 元素与来自WatchKit 对应元素之间的根本区别。UILabel 拥有一个名为text 的属性,通过该属性可以设置和检查标签文本,然而WatchKit 只拥有一个 方法:setText。如果想要在WatchKit 应用中跟踪元素的状态,则必须在扩展程序中由你自行 处理。 (9) 在扩展程序中创建一个Boolean 属性: private var sayingHello = true 现在,saySomething 方法需要跟踪的是该Boolean 属性的状态,而不是尝试检查标签文本。 (10) 更新saySomething 方法,使用button Outlet 更新按钮文本: @IBAction func saySomething() { if sayingHello { button.setTitle("Say Goodbye") messageLabel.setText("Hello Wrist!") sayingHello = false } else { button.setTitle("Say Hello") messageLabel.setText("Bye Wrist!") sayingHello = true } } 如果你耐心完成了前面的练习,而没有跳过练习直接运行应用,那么此时是你的耐心得 到回报的时候。 1.3 “对不起,我并没有Watch” 就像过去可以在其他iOS 设备上完成相关操作一样,Apple 提供了不必访问物理硬件就 可以为Apple Watch 开发应用的能力。虽然针对模拟器进行测试永远不会像使用真实设备那 第Ⅰ部分 入 门 10 样万无一失,但是当有限的物理设备访问会显著降低开发速度时,使用模拟器可以在工作流 程方面节约大量时间,其价值是无法估量的。 Apple Watch 系列可能是Apple 生产的最多样化的产品。在推出Apple Watch 时,共有38 种不同的型号可供选择,包括Apple Watch、Sport 和Edition 产品选择。价格范围从Sport 版 的349 美元到Edition 版令人瞠目结舌的17 000 美元。此时问题来了,如何能够安全地测试 应用是否可以在所有型号上运行而又不会花费太多资金?幸运的是,虽然不同产品在外观上 都不相同,但实际上所有产品都只有两个真正的差异:38mm Watch 和42mm Watch。 1.3.1 可以测试哪些内容? 运行Watch 代码的第一步是确定入口点。将应用安装到物理设备上后,可以通过以下4 种方式调用该程序: ● 直接通过Watch 主屏幕加载该应用 ● 通过在表盘上显示自定义表盘元素 ● 通过查看通知 ● 通过查看快捷视图 Xcode 7 所提供的Watch 模拟器能够测试所有这些交互,但通常并不会显而易见地告诉 你应该怎么做。运行应用后,可通过选择Hardware | Home(或者按住Ctrl+Command+H)来模 拟按下数字表冠(digital crown),从而将模拟器返回到表盘。此时可以向下拖动来显示通知中 心(Notification Center),或者向上拖动来显示快捷视图。但遗憾的是,通知和快捷视图并不会 显示。这种情况下,如何按用户可能使用的相同方式来测试代码呢? 1. 选择方案(希望所选的方案不会非常麻烦) 幸运的是,可使用WatchKit App 项目模板开发iOS 应用。当创建项目文件时,Xcode 还 会创建许多额外的方案,从而允许以各种不同的方式运行应用。如果想要查看这些方案,可 以通过主菜单选择Product | Scheme | Manager Schemes,请特别注意Xcode 所创建的第4 个额 外方案,如图1-11 所示。 图1-11 Manage Schemes 对话框——更多方案 第1 章 创建WatchKit 项目 11 正如所期望的那样,对话框中包含了标准的iOS 应用方案(HelloWrist),此外还包含了一 个专为所有WatchKit 应用创建的名为HelloWrist WatchKit App 的方案。需要生成并运行该方 案来执行应用,就像通过Watch 的主屏幕启动一样。该方案与Interface.storyboard 文件中的 界面控制器场景相对应,如图1-12 所示。 图1-12 Watch 应用的主界面 对于剩下的三个方案,因为在创建WatchKit App对象(如图1-2 所示)时选择了选项Include Notification Scene 和Include Glances Scene,所以分别创建了两个方案Notification-HelloWrist WatchKit App 和Glance-HelloWrist WatchKit App。通过运行使用了这些方案的应用,可以让 Watch 接收快捷视图或通知。此外,还可以通过Glance Interface Controller Scene(如图1-13 所 示)、Static Notification Interface Controller Scene 和Notification Controller Scene(如图1-14 所示) 来自定义这些视图的外观。 图1-13 Glance Interface Controller Scene 图1-14 Notification Interface Controller Scene 注意: 第8 章和第9 章将分别详细介绍如何使用快捷视图和通知。 第Ⅰ部分 入 门 12 为了启用图1-2 所示的Include Complication 选项,需要预先创建最后一个方案Complication- HelloWrist WatchKit App。该方案允许运行模拟器来测试自定义表盘元素。它是一个比听起来 更加简单的方案——仅是将模拟器启动到表盘,并对所显示的自定义表盘元素进行配置。第 7 章将详细介绍如何创建和测试自定义表盘元素。 2. 访问Watch 模拟器 如果想要选择用来运行iOS 应用的模拟器,需要打开方案选择菜单,并从当前可用的选 项列表中选择一个模拟器。显然,可以在该列表中找到Watch 模拟器: (1) 单击方案选项按钮的设备部分(右侧),查看模拟器列表,如图1-15 所示。 但遗憾的是,虽然列表中显示了许多iPhone 和iPad 模拟器选项,却没有Watch 模拟选 项。这是因为当前我们选择了HelloWrist App 方案,而该方案的对象是一个iOS 应用。如果 想要看到Watch 模拟器,则需要选择另一个不同的对象。 (2) 单击方案选择按钮的方案部分(左侧),显示可用的方案列表。 (3) 选择4 个HelloWrist WatchKit App 方案中的一个,从而切换到一个带有WatchKit 应 用目标的方案。 此时方案选择按钮的设备部分会发生变化,表明运行所选择的方案将启动iPhone 和 Watch 模拟器。因为单独启动Watch 模拟器是不可能的,所以选项包括了iPhone 和Watch 模 拟器组合,如图1-16 所示。 图1-15 如果选择了iOS 方案,则无法选择Watch 模拟器 图1-16 iPhone 和Apple Watch 模拟器组合 (4) 选择想要启动的模拟器组合。 默认配置包括iPhone 6 和iPhone 6 Plus 以及38mm 和43mm Apple Watch 选项。这些选 项应该足以满足大多数测试需求,但如果确实需要,也可以在Xcode 的Devices 部分创建更 多的组合。 Watch 模拟器通常存在iOS 模拟器的一些局限性。比如,不能同时在iPad 和iPhone 模拟 器上运行相同的应用。不能同时显示38mm 和42mm watchOS 模拟器。此外,也不能在运行 watchOS 模拟器的同时运行iPad 模拟器——虽然Apple Watch 与iPhone 之间关系紧密,却不 能与iPad 一起使用,甚至模拟也不行。 第1 章 创建WatchKit 项目 13 1.3.2 尝试HelloWrist! 到目前为止,你已经表现出值得称赞的耐心,现在是时候实际运行程序了。 (1) 从方案选择按钮的方案部分选择HelloWrist WatchKit App 方案。 (2) 单击Run 按钮,运行Watch 应用。 (3) 此时,在一个名为Simulator的进程中生成iOS应用,而在另一个名为Simulator(Watch) 的进程中生成watchOS 应用。虽然iOS 模拟器不会运行任何活动应用,却可以用来与Watch 模拟器进行通信。 应用会给出提示信息“Say Hello”,如图1-17 所示。请点击按钮,向watchOS 开发的美 好未来说Hello。 图1-17 某些人想说Hello 1.4 小结 到目前为止,我们已经完成了对WatchKit 的初步认识。虽然WatchKit 开发在很多方面 都与常规的iOS 开发类似,但它也包含了许多限定以及完成工作的新方法,所以买一本关于 该主题的书是非常正确的。你是非常幸运的! 在第2 章,我们将学习WatchKit App 项目模板的布局。此外,还将讨论如何向现有的iOS 项目添加watchOS 配对应用。