一、Apple Watch简介:
两个不同的可执行文件:
a>在Apple Watch上运行的Watch应用,Watch应用只包含与应用程序的用户界面有关的storyboards和资源文件。
b>在用户iPhone上运行的WatchKit应用扩展,WatchKit应用扩展则包含了用于管理、监听应用程序的用户界面以及响应用户交互的代码。
注意:Watch应用需要尽可能实现Apple Watch提供的所有交互动作。由于Watch应用目的在于扩展iOS应用的功能,因此Watch应用和WatchKit应用扩展将被捆绑在一起,并且都会被打包进iOS应用包。如果用户有与iOS设备配对的Apple Watch,那么随着iOS应用的安装,系统将会提示用户安装相应的Watch应用。
二、Watch App操作步骤:
a>创建Watch应用
b>创建Glance界面
b>自定义通知界面
三、配置Xcoe项目:
1、向iOS应用中添加Watch应用:
1. 打开现有的iOS应用项目.
2. 选择 File > New > Target,然后选中Apple Watch
3. 选择 Watch App
4. 单击 Next
5. 如果您想要使用glance或者自定义通知界面,请选择相应的选项, 我们建议您激活应用通知选项。选中之后就会创建一个新的文件来调试该通知界面。如果您没有选择这个选项,那么之后您只能手动创建这个文件了。
6. 单击 Finish
2、应用对象的结构:
Watch App ——————> WatchKit Extension ——————> iOS App
Watch App Target ——————> WatchKit Extension Target ——————> iOS Target
3、编译、运行以及调试程序
为glance和通知配置自定义编译方案:
1. 选择现有的Watch应用方案.
2. 从方案菜单中选择Edit Scheme.
3. 复制现有的Watch应用方案,然后给新方案取一个合适的名字。比如说,命名为“Glance - My Watch app”,表示该方案是专门用来运行和调试glance。
4. 选择方案编辑器左侧栏的Run选项
5. 在信息选项卡中,选择合适的可执行对象
6. 关闭方案编辑器以保存更改
四、Watch应用的体系结构:
1、Watch应用和WatchKit应用扩展之间的通信:
Apple Watch : Watch App ——————> WatchKit
iPhone : WatchKit Extension ——————> WatchKit
2、启动Watch应用:
Apple Watch : Watch App ——————>Load Initial interface controller ——————> initialize UI ( initWithContext方法) ——————> Display UI(willActivate方法)
3、界面控制器的生命周期:
Apple Watch : Launch App ——————> Load UI ——————> initialize UI(initWithContext方法) ——————> Display UI(willActivate方法) ——————> Load Initial interface controller(Various action methods 方法) ——————> User stops interacting(didDeactivate方法)
4、WKInterfaceController的主要方法:
- (void)awakeWithContext:(nullable id)context;
这个方法用来准备显示界面。借助它来加载数据,以及更新标签、图像和其他在故事板场景上的界面对象。
- (void)willActivate;
这个方法可以让您知道该界面是否对用户可视。借助它来更新界面对象,以及完成相应的任务,完成任务只能在界面可视时使用。
- (void)didDeactivate;
使用didDeactivate方法来执行所有的清理任务。例如,使用此方法来废止计时器、停止动画或者停止视频流内容的传输。您不能在这个方法中设置界面控制器对象的值,在本方法被调用之后到willActivate方法再次被调用之前,任何更改界面对象的企图都是被忽略的。
5、与Containing iOS应用共享数据:
如果您的iOS应用和WatchKit应用扩展都依赖于相同的数据,那么您可以使用共享程序组来存储数据。共享程序组是一个位于本地文件系统的区域,应用扩展和应用都能够访问。由于两个程序在不同的沙箱环境中运行,它们一般情况下都不与对方共享文件和进行通信。共享程序组让共享数据成为可能。你可以使用这个空间来存储共享的数据文件或者在两个程序间交换消息。
您可以在iOS应用和WatchKit应用扩展中的Capabilities选项卡中启动共享程序组。激活这项功能后,Xcode将会为每个对象添加授权文件(需要的话),并给那个文件添加com.apple.security.application-groups授权。要共享数据,这两个对象必须选择相同的共享程序组。
程序运行时,您可以通过在共享容器目录中读写文件以在两个程序间共享数据。要访问容器,请使用NSFileManager中的containerURLForSecurityApplicationGroupIdentifier:方法来接收该目录的根路径。使用方法返回的URL来枚举目录内容或者在目录中为文件创建新的URL。
五、使用iOS技术注意事项:
1、避免使用需要用户权限的技术,比如Core Location。在WatchKit应用扩展中使用该技术的话,可能会在您第一次请求使用时导致用户的iPhone上显示出一个意想不到的提示。更糟糕的是,这个状况可能会在任何时间出现,即使用户的iPhone在他们的口袋里并且屏幕是锁定的。
2、不要使用后台执行模式的技术。WatchKit应用扩展只考虑在前台运行的情况,并且其只在用户和对应的Watch应用交互时运行。因此,支持后台运行的某些技术在WatchKit应用扩展中并不被支持。
3、避免使用需要长时间运行的技术。WatchKit应用扩展在用户停止和对应的Watch应用交互后便迅速暂停。由于与Watch应用的交互通常是短暂的,因此应用扩展可能会在请求的数据到达前暂停运行。
六、WatchKit App 概要:
1、界面控制工作流程:
界面控制器(Interface controller)管理你storyboard的场景内容。每个界面控制器都使用outlet来保存场景中的引用对象,并定义action方法来响应用户交互。在运行时,你可以使用界面控制器的initWithContext:和willActivate方法来配置界面。在这些方法里,你的操作任务如下:
a》获取你想展示的数据。
b》设置初始化和配置标签,图片和其他控件。
c》根据你的需要,展示或隐藏你的界面对象。
2、整合你的故事版场景:
3、在运行时更新界面:
在运行过程中,界面控制器能让对象在相应的storyboad场景中做如下改变:
a》设置或修改数据变量。
b》支持改变对象的外观。
c》改变对象的透明度。
d》显示或隐藏对象。
Responding to User Interactions(响应用户界面方法):
- (IBAction)buttonAction:
- (IBAction)pickerAction:(NSInteger)index:
- (IBAction)switchAction:(BOOL)on:
- (IBAction)sliderAction:(float)value:
- (IBAction)menuItemAction:
4、界面的国际化:
对于文本和图片的国际化处理,可以使用iOS和OS X应用相同的技术:
a》使用NSLocalizedString宏来从资源文件夹加载字符串。
b》使用NSNumberFormatter对象来格式化数值型变量。
c》使用NSDateFormatter对象来格式化日期。
七、WatchKit App 界面导航:
a》实现分层界面:
在该界面控制器中,您可以通过调用当前界面控制器的pushControllerWithName:context:方法在屏幕上推出一个新的界面控制器。
想要解除界面控制器,可调用其popController方法。
b》实现基于分页的界面:
可以创建下一页的segue,以便在app的storyboard文件中配置分页界面。想要创建该segue:
1.对您希望作为第一屏的界面控制器执行Control-click操作,并将其拖拽到不同的界面控制器中。
应该强调第二个界面控制器,以指明segue是可用的。
2.释放鼠标按钮。
3.从relationship segue面板中选择next page。
通常在storyboard文件中配置一组初始的页面集合。当app启动时,WatchKit会实例化和初始化您的初始界面控制器,然后是分页界面中的其他界面控制器。如果您想改变一组界面控制器,请在初始界面控制器的init方法中调用reloadRootControllersWithNames:contexts:方法。调用该方法会使得WatchKit在尝试展示界面中任何其他页面之前加载新的界面控制器。您也可以在app运行时调用reloadRootControllersWithNames:contexts:方法来改变展示中的页面集合。
当系统加载您的WatchKit app界面时,它将实例化和初始化组成界面的所有界面控制器。当用户从一个界面控制器切换至下一个时,它将调用当前界面控制器的didDeactivate方法,以及即将展示的界面控制器的willActivate方法。willActivate方法可确保界面中的信息是最新的。
c》以模态形式展示界面控制器
1、调用presentControllerWithName:context:方法来模态地展示单个界面控制器。
2、调用presentControllerWithNames:contexts:方法展示两个或者多个使用分页布局的界面控制器。
七、WatchKit App 界面对象:
1、创建界面对象:
@property (weak, nonatomic) IBOutlet WKInterfaceLabel* label;
2、在设计阶段配置界面:
注意:可以使用一个WKInterfaceLabel对象来更改标签的文本、颜色以及字体,不过却不能更改它的行数或者是行高。
3、在运行时更改界面:
- (instancetype)initWithContext:(id)context {
// Always call super first.
self = [super initWithContext:context];
if (self){
// It is now safe to access interface objects.
[self.label setText:@“Hello New World”];
}
return self;
}
4、响应用户交互:
请使用按钮、开关以及其他的交互控件来更改应用状态。当点击按钮或某一控件的值发生变化时,WatchKit会调用界面控制器中相关的动作方法(action method)。每种界面对象针对其动作方法都有一个必须的格式,如下所示:
- (IBAction)buttonClicked;
5、隐藏界面对象:
在设计布局时,隐藏起某些项目就可以当做是将其从布局中完全删除。如果要隐藏某个对象,只需要调用setHidden:方法并为其传递YES值就行了。
八、WatchKit App 文本、标签以及图片:
1、使用自定义字体:
UIFont* menloFont = [UIFont fontWithName:@"Menlo" size:12.0];
NSAttributedString *attrString = [[NSAttributedString alloc]
initWithString:@"My Formatted Text"
attributes:@{NSFontAttributeName: menloFont}];
[self.myCustomFontLabel setAttributedText:attrString];
2、自定义系统字体:
3、国际化您的文本代码:
使用基于Xcode国际化支持的storyboard和xib文件。基于国际化可以让你仅仅只用一个storyboad文件就能支持所有的本地化。本地化字符串分别存在特定的区域语言字符串中。
使用NSLocalizedString类的宏定义来让程序自动检索本地化字符串。
通过NSNumberFormatter类使用用户所在区域和本地的设置来格式化数值型的值。
通过NSDateFormatter类使用用户所在区域和本地设置来格式化时间。
九、WatchKit App 表格:
1、配置Row Types:
Row Type是一个在table中以单行形式展示数据的模板。每个table必须至少有一个row type,您可以根据需求定义额外的row type。您可以用row type区分table中的不同内容。比如您可能在内容行上、标题和注脚上使用不同的类型。当您为界面控制器场景添加table时,Xcode会自动创建初始的row types供您配置。
为table添加row types:
a>在storyboard文件中选中table对象.
b>打开Attributes inspector.
c>使用Rows属性更改可用row type数量.
为row type定义一个row controller类:
a>为WatchKit扩展添加一个新的Cocoa Touch类
b>让新类继承NSObject
c>为每个计划在运行时访问的标签、图片或者控件添加声明的属性。声明属性可使用以下格式,请更改类以匹配相应的界面对象
在storyboard中配置row type:
a>在storyboard文件中选中row controller对象
b>将row controller的Identifier属性设置为唯一值,随后您会在创建表格行时使用该标识符。在行类型中该值必须是唯一的,但是实际值还是由您来定夺。在Attributes inspector中设置该值。
c>将row type的类设置为您的自定义类。您需要在Identity inspector中设置类信息。将row type元素和类中对应的outlets连接起来
d>将storyboard文件中的项目和outlets连接并绑定。当您在代码中配置table时,WatchKit会在运行时使用该信息实例化对应的类
2、运行时配置table内容:
创建并配置列表行:
a>先决定你需要创建的行的数目和类型,这取决于你想要展示的数据类型
b>使用setRowTypes:或者setNumberOfRaws:withRowType:方法来创建。这两个方法都会在界面上创建新的列表行,并且会在WatchKit扩展中实例化对应的类。这些实例被保存在table中,且可通过rowControllerAtIndex:方法访问
c>使用rowControllerAtIndex:方法遍历表格中的每一行
d>使用row controller对象来配置每一行中的内容
十、WatchKit App 情景菜单:
1、设计菜单项:
每个菜单项包含一个可点击区域和一个标题。可点击区域由纯色背景和您提供的图片组成。图片必须是模板图片,其alpha通道指定了绘制在纯色背景上的图形。
2、为界面控制器添加情景菜单:
情景菜单中的菜单项目总数不能超过4个,不管是在storyboard文件中定义还是以编程方式添加,或者组合两种方式。
1.打开storyboard文件。
2.从工具库中拖拽一个菜单项,并将其添加到界面控制器场景中。初始菜单包含一个单独的菜单项目。
3.最多从库中拖拽3个菜单项到菜单中。你还可以使用菜单的Attributes检查器来设置菜单项数量,您添加的菜单项不能被移除。
4.对于每个菜单项目,可使用Attributes检查器来指定菜单的标题和图片,这两者都是需要的。
5.在界面控制器类中将每个菜单项和操作连接起来。菜单操作方法格式如下:
- (IBAction)doMenuItemAction
想要在运行时添加菜单项目,请调用界面控制器对象的addMenuItemWithImage:title:action:或者addMenuItemWithImageNamed:title:action:方法。您添加的菜单项被附加到storyboard文件中指定的对象上。以编程方式添加的菜单项目持续附属于菜单,直到您明确地移除它们或者您的界面控制器解除配置。
十一、Glance开发基础:
1、Glance的生命周期:
Glance界面控制器的生命周期和其他WatchKit界面控制器一样,不过glance的界面控制器的初始化要早于其它,以便于glance能快速的显示给用户。
2、Glance界面指南:
遵循下面的指南来填充内容:
1.Glance的设计目的在于快速的传达信息。不要显示一堆文字。适当的使用图像、颜色和动画来快速传达信息。
2.聚焦在最重要的数据上。Glance不是你的应用的替代。就像Watch app是对应的iOS app的缩水版,你也可以把glance看做Watch app的缩水版。
3.不要在glance界面中包含交互控件。比如按钮、选择器、滑动器和菜单。
4.避免使用表格和地图。尽管并没有禁止你这么做,手表上有限的控件让表格和地图不是那么有用。
5.让显示的信息保持及时。使用所有可用的资源,包括时间和地理位置,来向用户提供有用的信息。并且注意更新你的glance,以避免因为glance初始化到显示花费的时间而让信息过时。
十二、管理Glance界面:
1、实现一个Glance界面控制器:
a.使用initWithContext:方法来初始化你的glance界面,并且设置标签和图像的初始值。
b.基于内容的改变,使用willActivate来更新glance。
2、自定义从Glance启动应用:
在触摸glance时启动并显示一个不同的界面控制器,你需要按如下步骤操作:
a.在glance界面控制器中:
配置glance的initWithContext: 和 willActivate ,这一步和其他情况是相同的。
调用updateUserActivity:userInfo:方法,并且使用userinfo参数来传达你的应用glance的状态。
b.在你的应用的主界面控制器:
实现actionForUserActivity:context: 方法,使用提供的userinfo字典来确定显示哪个界面控制器,你还应该生成一个上下文对象并将它传递给指定的界面控制器。
十三、Notification 通知的一些要点:
1、Short-Look 界面
Short-Look 界面是一个不可滚动的视图,并且不可以被定制。系统使用一个通用的模板来显示应用名称、图标,以及存储在本地或远程通知消息中的标题。
2、Long-Look 界面
Long-Look 界面是一个可滚动的界面,它显示了通知的全部内容,以及所有的关联按钮。如果您没有提供自定义的通知界面,那么 Apple Watch将会显示默认界面,里面包括了应用图标、通知的标题,以及提示消息。而如果您提供了自定义的通知界面,那么 Apple Watch 将会显示它。
Long-Look 通知界面分为三个区域:
a.Sash顶部——》System-Provided
b.Content Area中间部分——》App-Provided content
c.Bottom Area——》App-Defined actions
3、为通知上添加按钮
按钮通过为通知提供封装的动作响应来帮用户节省时间。Apple Watch使用iOS 应用注册的交互通知界面来显示按钮。在 iOS 8 以及更高版本中,应用都需要使用UIUserNotificationSettings 对象来注册它们显示的生成通知对话框。一旦对象创建,应用也同样可以指定自定义通知类别以及其对应的按钮动作。Apple Watch使用这个类别信息来添加相应的按钮到 Long-Look 界面上。
4、让按钮响应单击动作
前台按钮动作将启动您的 Watch 应用,然后将按下的按钮的 ID 传递给主界面控制器。
十四、Notification 自定义通知界面:
1、自定义通知界面含有两个独立的界面:
一个静态界面:静态界面是一个简单的界面,它仅仅只含有通知的提示信息,以及您在设计时配置的静态图像以及文本信息。
一个动态界面:动态界面显示了完整的自定义通知内容样式,并且它可以包含由 WatchKit 扩展提供的定制内容和图形。
2、配置自定义界面的通知类型:
当生成远程通知时,您的服务器要通过在其`aps`字典中包含category键的值来指定通知类型。`category`的键值要和您在 iOS 应用以及您在通知类别对象中的 Name 属性指定的一样。例如,在图15-2中,类别文本是`MeetingInvite`。
3、配置静态通知界面:
a.所有的图像必须驻留在 Watch 应用包中
b.界面不能包含控件、表格、地图,以及其他交互元素
c.界面的`notificationAlertLabel`输出口必须与某个标签相关联。标签的文本设置为通知的警告信息。其他的标签文本不变,并且只能够在设计时设置。
d.除了和`notificationAlertLabel`输出口相连的标签外,在静态通知场景中的标签和图像是不能够改变的。当您在设计界面时请记住这条准则,并确保每个标签的文本是合适的。
4、配置动态通知界面:
动态通知界面给用户提供了一个更丰富的通知体验。借助动态界面,您可以显示很多的内容。您可以添加额外的信息,配置多个标签,动态地生成内容,等等。
5、设计动态界面
可在绝大多数界面上使用标签、图像、组以及分隔符。
您可能想要在需要的时候使用表格和地图。
不要包含有按钮、开关,或者其他交互控件。
6、在运行时配置动态界面
界面初始化之后,WatchKit将负载数据传输到通知界面控制器的不同方法中。对于远程通知来说,WatchKit 调用didReceiveRemoteNotification:withCompletion:方法。对于本地通知来说,它调用didReceiveLocalNotification:withCompletion:方法。请使用接受到的数据来配置您的通知界面。界面配置完成后,您必须要调用所提供的完成处理代码块来让 WatchKit 知道您的界面已经准备就绪。
Watch App ——————>Locate the custom UI in the notification storyboard( init方法 ) ——————> Process the notification( didReceiveRemoteNotification:withCompletion:方法 ) ——————> Display the Notification UI