Apple Watch应用开发:从再造墨迹天气谈起
zhezhongyun 2025-05-02 22:37 29 浏览
编者按:本文作者刘超在2012年加入墨迹天气,主要负责iOS平台软件开发工作。在今年年初,墨迹天气团队针对Apple Watch的硬件与交互特点,对应用做了重新设计与开发。作者从软件开发角度,分享了墨迹天气团队在开发过程中发现的问题、误区,以及解决之道。
Apple Watch的设计误区
WatchKit发布第一时间,我们的产品经理和设计师就根据设计规范和官方宣传动画迅速出了一版设计原型。Apple Watch版应用中囊括墨迹天气iPhone版的大部分功能,从实况到预报,再到时景和分享,其中包括一些新的交互,如使用Digital Crown切换短时和多天预报、缩放时景图片,在消息推送达到后直接在该推送下编辑信息回复。它相当于一个微缩版本的墨迹天气。
随后程序员也很快加入到这个项目里。当我们研究过Programming Guide和Watchkit framework Reference后,失望的发现宣传视频上展示的操作:Digital Crown、表面触感、地图缩放等是不对开发者开放的。于是我们开始重新推敲交互,设计师也发现不能再像设计iPhone应用那样自由的设计细节。由于最初我们都是没有实际的佩戴体验的,只能从宣传片和设计开发指南中找思路,揣摩用户的使用场景和心理。通过和Apple方面有佩戴经验的负责人交流,我们发现最开始的设计方向是不对的,我们不应该把设计重心Apple Watch的主程序上,而是重点设计Glance和Notification。作为一款手表上的应用程序,及时方便地查看才是它最常见的应用场景。曾经看到一位没有使用过Apple Watch的网友调侃:在那么小的屏幕上操作带来的麻烦完全抵消了从兜里掏出手机的麻烦。
Watch应用开发的五条小技巧
WatchKit提供的是一套全新的界面类。令人熟悉的地方是,大多数方法和属性的命名都有很好的延续性,几乎不需要重新学习就能够大概看出其含义。不同的是所有的界面控件都继承自 WKInterfaceObject,也就是说这些界面控件不再是继承自UIView的控件实体,而更像是控制真正界面的代理控制器。
在进行开发之前,我们要先了解一下Watchkit是如何工作的。实际上一个Watch应用分为两部分,负责界面的WatchKit App,只包括storyboard和asset catalog,它运行于Apple Watch上,另一个是负责逻辑部分的WatchKit Extension,则运行于iPhone上。开发者可能会担心,这样会不会加大开发的难度呢?答案是完全不会!Apple Watch和iPhone使用Bluetooth LE 和 Wi-Fi 技术进行通信,整个通信过程实在后台完全自动进行的,所以即使界面和交互在Apple Watch上,逻辑在iPhone上,我们却根本不需要操心,只要像常规那样处理界面属性赋值和交互响应即可,确实很酷!
首先是界面开发,在使用WatchKit开发时,不会再出现“代码写UI还是Xib写?”这样的带有争议的问题,因为Watch应用只能用StoryBoard进行开发,我猜想是为了更好的控制Watch应用的界面一致性,除此之外还有比较多限制。譬如不能在运行时动态增减界面元素,只能通过设置隐藏属性来调整界面展示;元素之间不能出现叠加,只能按纵向横向依次排列; Glance必须从官方模版中选择一个来使用,不能自由堆砌界面元素等等。不过最终开发下来,发现只要运用得当,空间还是很大的,在此我们根据实践总结了一些小技巧:
使用 WKInterfaceGroup、WKInterfaceButton的- setBackgroundImageNamed:和-
startAnimatingWithImagesInRange:duration:repeatCount:方法在背景上增加图片或者动画,这样就可以使控件和图形实现叠加。有些小伙伴可能会觉得很惊奇,“什么?WKInterfaceButton也可以作为容器放置控件?”是的,只要在控件的Attributes inspector里把Button的Content属性由Text修改为Group即可,这样我们就可以像使用Group一样使用button了。抬手即看的短暂应用场景要求我们必须开发出层次简洁、操作流畅的应用,过程中我们发现WKInterfaceMenu的使用效果非常生硬,实际操作时需要长按才会响应,另外当弹出的选项偏少时,界面并不美观,所以后来用WKInterfaceButton的轻点事件取代了这种长按操作。
在控件的Attributes inspector里,可以针对38mm和42mm的Apple Watch分别设置属性。
如果想让一组横向放置的N个控件等宽,可又因为不知道设备类型而不能设置具体的宽度,该怎么办呢? 一种比较土的办法是,在程序运行后,通过获取屏幕宽度来动态的设置控件宽度。另一种方法是直接在该控件的属性设置里把宽度设置为Reletive to Container,然后在其下方的输入框内填写所占比例,例如5等份,就填写0.2,这样系统会按照你的设置自动帮你设置好。
在传统的基于界面的iOS应用中,程序可以在AppDelegate里做好界面展示的准备工作,但是Watch应用必须直接指定某个界面为入口。如果你的根界面是一个基于分页的结构(page-based), 可能会碰到这样的问题:程序在启动后才动态的决定分页数,所以需要在页面内调用
reloadRootControllersWithNames来重新加载,如果加载的页面中不仅包括加载者自身又没有做处理的话,就会无限加载下去,这时候你可以使用一个static变量来解决无限reload的问题,如下:
- (void)awakeWithContext:(id)context {<br> [super awakeWithContext:context];<br> static BOOL bReload = NO;<br> if (!bReload) {<br> bReload = YES;<br> //计算分页数,准备各分页context数据<br> //调用[WKInterfaceController reloadRootControllersWithNames: contexts:]加载分页<br> }<br> else {<br> //处理输入的context,这里不加载界面,willActivate执行时再lazy加载<br> }<br>}
当用户抬起手腕打开Glance想看一下天气时,如果程序此时才去进行数据请求,用户就会面对一个大大的N/A界面,需要等上1~2秒,直到网络请求成功,才会显示最新的天气信息。这会带来较差的使用体验。相对来说,我认为比较好的做法是,先让iPhone应用支持后台刷新的系列功能,包括:silent notification、background fetch。如此一来,当用户查看Glance时,呈现给他的是近期更新过的数据,随后程序做出判断,如果这个还需要呈现给用户更新的数据就立即进行网络请求,请求成功后再更新界面。
数据共享与通信
Watch应用和containing iOS App之间可以通过共享数据区进行数据共享。首先启用App Groups,然后在共享容器内根据要共享数据的性质来决定是用NSUserDefaults还是直接在共享区读写文件。官方Demo推荐用NSFileCoordinator来进行文件读写,以完成多进程间的同步。不过,我自己在实践过程中发现,使用NSFileCoordinator时必须特别小心,使用不当会造成因资源引起的死锁。当时情况是这样的:程序上的一个bug导致在个别情况下会出现特别频繁的IO,以致程序几乎失去了响应。这时候如果直接将程序kill掉,资源所在目录有几率发生死锁,如果重启App,程序会卡死在NSFileCoordinator的
coordinateReadingItemAtURL方法上。该方法的回调block长时间得不到执行,以致于iOS的”看门狗”会直接将App干掉,启动不起来,只能依靠重启系统来解决。对App开发者来说简直是“人间惨剧”,这种情况下没有几个用户会不删掉App的。
由于atch应用只有运行、挂起、终止三种状态,所以一旦你正在使用NSFileCoordinator写文件时被挂起,它就没有机会让出资源所有权。要解决这个问题,需要使用原子安全的保存操作,如UIDocument。
如果你需要Watch应用同containing iOS app进行通信,可以使用WKInterfaceController类的类方法openParentApplication,反过来如果需要containing iOS app同watch app通信,一种办法是通过在数据共享区读写文件,然后让watch app监听该文件从而做出响应;另一种方法,是使用Darwin Notification Center,具体开发过程,可以参照 官方的建议。
性能方面
关于这一点,官方给予的建议非常明确,简要列举如下:
尽可能减少iPhone和Apple Watch之间的数据通信,比如尽可能把图片存在WatchKit app bundle里,这样显示图片的时候会更快更省电。
仅更新界面上改变的部分,比如需要对 table新增了一行数据,不要重新加载整个table。
减少分页结构应用的加载时间,在init和awakeWithContext做尽可能少的处理,界面如何展示的问题放在WillActivate内处理。
让一个Controller负责尽可能少的场景,因为当显示其中一个场景时必须要隐藏不需要的控件,但是隐藏控件也会被创建,就会影响加载速度。
其它Tips:
官方论坛的Apple Watch模块里有很多有价值的问答,苹果的工程师会在里面对开发者的疑问进行解答。推荐下载官方Demo Lister,这是一个非常不错的开发示例。但是要注意,Demo里大量使用iOS 8及其以上的API,如果你的App还需要支持iOS 8以下的系统,在Copy代码时请做好兼容。
XCode 6.2版本有一个小bug,就是必须把相关target的Bundle Display Name 和 Bundle Name都配置为我们的应用名,才会在Watch应用启动和iPhone上Apple Watch的配对程序里正确的显示应用名称。
另外,还要给使用XCode6.2的开发者提个醒,不正确的现实应用名称有可能会被审核拒绝。需要支持国际化的开发者要针对所支持语言在infoPlist.strings内配置CFBundleName的值即可。
写在最后
根据Apple在iOS系统上日益开放的策略,我们有理由相信,随着时间的推移WatchKit会开放给开发者越来越多的API。各种App也会更准确的捕捉到Apple Watch的应用场景,开发者也会有更大的舞台去发挥!
作者简介:刘超,2012年加入墨迹天气,主要负责iOS平台软件开发工作。欢迎感兴趣的中高级iOS工程师交流。chao.liu#moji.com
CSDN移动将持续为您优选移动开发的精华内容,共同探讨移动开发的技术热点话题,涵盖移动应用、开发工具、移动游戏及引擎、智能硬件、物联网等方方面面,如果您有想分享的技术、观点,可通过电子邮件(tangxy#csdn.net,请把#改成@)投稿。
第一时间掌握最新移动开发相关信息和技术,请关注mobilehub公众微信号(ID: mobilehub)。
相关推荐
- JavaScript中常用数据类型,你知道几个?
-
本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!作者|慕课网精英讲师Lison这篇文章我们了解一下JavaScript中现有的八个数据类型,当然这并不是JavaScr...
- 踩坑:前端的z-index 之bug一二(zh1es前端)
-
IE6下浮动元素bug给IE6下的一个div设置元素样式,无论z-index设置多高都不起作用。这种情况发生的条件有三个:1.父标签position属性为relative;2.问题标签无posi...
- 两栏布局、左边定宽200px、右边自适应如何实现?
-
一、两栏布局(左定宽,右自动)1.float+margin即固定宽度元素设置float属性为left,自适应元素设置margin属性,margin-left应>=定宽元素宽度。举例:HTM...
- 前端代码需要这样优化才是一个标准的网站
-
网站由前端和后端组成,前端呈现给用户。本文将告诉您前端页面代码的优化,当然仍然是基于seo优化的。 就前端而言,如果做伪静态处理,基本上是普通的html代码,正常情况下,这些页面内容是通过页面模...
- 网页设计如何自学(初学网页设计)
-
1在Dreamweaver中搭建不同的页面,需要掌握HTML的语句了,通过调整各项数值就可以制作出排版漂亮的页面,跟着就可以学习一些可视化设计软件。下面介绍网页设计如何自学,希望可以帮助到各位。Dre...
- 1、数值类型(数值类型有)
-
1.1数据类型概览MySQL的数据类型可划分为三大类别:数值类型:旨在存储数字(涵盖整型、浮点型、DECIMAL等)。字符串类型:主要用于存储文本(诸如CHAR、VARCHAR之类)。日期/...
- 网页设计的布局属性(网页设计的布局属性是什么)
-
布局属性是网站设计中必不可少的一个重要的环节,主要用来设置网页的元素的布局,主要有以下属性。1、float:该属性设置元素的浮动方式,可以取none,left和right等3个值,分别表示不浮动,浮在...
- Grid网格布局一种更灵活、更强大的二维布局模型!
-
当涉及到网页布局时,display:flex;和display:grid;是两个常用的CSS属性,它们都允许创建不同类型的布局,但有着不同的用法和适用场景。使用flex布局的痛点当我们使...
- React 项目实践——创建一个聊天机器人
-
作者:FredrikStrandOseberg转发链接:https://www.freecodecamp.org/news/how-to-build-a-chatbot-with-react/前言...
- 有趣的 CSS 数学函数(css公式)
-
前言之前一直在玩three.js,接触了很多数学函数,用它们创造过很多特效。于是我思考:能否在CSS中也用上这些数学函数,但发现CSS目前还没有,据说以后的新规范会纳入,估计也要等很久。然...
- web开发之-前端css(5)(css前端设计)
-
显示控制一个元素的显示方式,我们可以使用display:block;display:inline-block;display:none;其中布局相关的还有两个很重要的属性:display:flex;和...
- 2024最新升级–前端内功修炼 5大主流布局系统进阶(分享)
-
获课:keyouit.xyz/14642/1.前端布局的重要性及发展历程前端布局是网页设计和开发的核心技能之一,它决定了页面元素如何组织和呈现。从早期的静态布局到现代的响应式布局,前端布局技术经历了...
- 教你轻松制作自动换行的CSS布局,轻松应对不同设备!
-
在网页设计中,自动换行的CSS布局是非常常见的需求,特别是在响应式设计中。它可以让网页内容自动适应不同屏幕尺寸,保证用户在不同设备上都能够获得良好的浏览体验。本文将介绍几种制作自动换行的CSS布局的方...
- 晨光微语!一道 CSS 面试题,伴你静享知识治愈时光
-
当第一缕阳光温柔地爬上窗台,窗外的鸟鸣声清脆悦耳,空气中弥漫着清新的气息。在这宁静美好的清晨与上午时光,泡一杯热气腾腾的咖啡,找一个舒适的角落坐下。前端的小伙伴们,先把工作的疲惫和面试的焦虑放在一边,...
- 2023 年的响应式设计指南(什么是响应式设计优缺点)
-
大家好,我是Echa。如今,当大家考虑构建流畅的布局时,没有再写固定宽度和高度数值了。相反,小编今天构建的布局需要适用于几乎任何尺寸的设备。是不是不可思议,小编仍然看到网站遵循自适应设计模式,其中它有...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 教程 (33)
- HTML 简介 (35)
- HTML 实例/测验 (32)
- HTML 测验 (32)
- JavaScript 和 HTML DOM 参考手册 (32)
- HTML 拓展阅读 (30)
- HTML常用标签 (29)
- HTML文本框样式 (31)
- HTML滚动条样式 (34)
- HTML5 浏览器支持 (33)
- HTML5 新元素 (33)
- HTML5 WebSocket (30)
- HTML5 代码规范 (32)
- HTML5 标签 (717)
- HTML5 标签 (已废弃) (75)
- HTML5电子书 (32)
- HTML5开发工具 (34)
- HTML5小游戏源码 (34)
- HTML5模板下载 (30)
- HTTP 状态消息 (33)
- HTTP 方法:GET 对比 POST (33)
- 键盘快捷键 (35)
- 标签 (226)
- HTML button formtarget 属性 (30)
- CSS 水平对齐 (Horizontal Align) (30)