Watch App结构及技术调研。
- Watch App,运行在Apple Watch上,只包含与UI相关的storyboards和资源文件
- WatchKit Extension,运行在iPhone或Apple Watch(WatchOS 2)上,包含应用的管理和响应用户交互的代码。
Watch App只能随iOS App一起发布,应用安装后会同步至配对的Watch上,用户可以在“我的手表”中设置是否同步Watch应用。
第三方Watch App必须依赖于iPhone5以上的设备运行。
官方结构图如下:(含WatchOS 2)
Watch App界面:
- App主界面
- Glance界面
- Notification自定义界面
主界面包含完整的用户界面,用户通过点击应用Icon启动应用,查看处理数据。
Glance界面是只读的,不能包含可交互的控件,点击界面后跳转到应用主界面。此界面只有一屏,所以要显示重要、及时的信息。
Notification界面可以自定义本地或远程通知的显示样式,可添加一些图片、文字等内容。
更多watchOS内容参考https://developer.apple.com/watchos/pre-release/
创建一个Watch App工程
创建Watch App并添加Notification和Glance。
关于BundleID
xcode会以iOS应用的BundleID加后缀的方式自动为WatchKit Extension和Watch App生成BundleID。
|应用|BundleID| |—|—| |iOS App|com.td.demo| |WatchKit Extension|com.td.demo.watchkitextension| |WatchKit App|com.td.demo.watchkitapp|
Watch App代码交互详解
Watch App
-
点击Watch app icon
未初始化:init -> awakeWithContext -> willActivate
已初始化:willActivate -
锁屏/Back键:DidDeactivate
参考代码:
// InterfaceController.m
@implementation InterfaceController
- (instancetype)init {
self = [super init];
if (self) {
// 可在此处进行一些初始化操作
}
return self;
}
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// 可在此处配置界面对象
}
- (void)willActivate {
// WatchApp视图即将可见
[super willActivate];
}
- (void)didDeactivate {
// WatchApp视图已不可见
[super didDeactivate];
}
@end
Glance
Glance对于Watch App并不是必须的,并且最多只能有一个。
界面分为上下两个区域,上区有12种样式可选,下区有24种样式可选。在Group中可以添加无交互的控件,但尽量不要使用地图和表格控件。
- 切换至Watch App的Glance
未初始化:init -> awakeWithContext -> willActivate
已初始化:willActivate - 锁屏/Back键/切换到其他Glance/进入Watch app:DidDeactivate
- 点击Glance进入Watch App(代码交互参考Watch app)
参考代码:
// GlanceController.m
@implementation GlanceController
- (instancetype)init {
self = [super init];
if (self) {
// 可在此处进行一些初始化操作
}
return self;
}
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// 可在此处配置界面对象
}
- (void)willActivate {
// Glance视图即将可见
[super willActivate];
}
- (void)didDeactivate {
// Glance视图已不可见
[super didDeactivate];
}
@end
Notification
Notification界面分为Short-Look和Long-Look两种,而Long-Look又分为Static和Dynamic两种。
Short-Look
只有一屏不可滚动、不可交互,UI由系统提供不能改变。Short-Look和iOS通知的条幅一样都是系统控制的,应用中无法得到通知显示等事件。
本地通知或远程通知的Title不为空显示Title和“应用名”,否则只显示应用名。
Short-Look to Long-Look
系统设置:在iPhone的“Apple Watch–我的手表–通知”中的“隐藏通知内容”:
关:Watch上显示Short-Look约一秒时间会自动跳转到Long-Look界面。
开:点击Short-Look界面跳转到Long-Look界面。按Back键Short-Look界面消失,可在“通知列表”中找到该通知。
在Short-Look界面锁屏30秒内点亮屏幕依然是Short-Look界面,否则界面消失,可在“通知列表”中找到该通知,该状态由系统控制,开发者无法参与。
Long-Look
一个Watch App可以创建多个Long-Look,每个Long-Look的Category需要设置为不同的名字。
Long-Look可以分为:
- 显示系统默认样式的Long-Look界面
- Default Long-Look
- 具有特定category属性Long-Look界面
通知到达后会根据category属性来显示相应的Long-Look界面
Dynamic & Static
如果Long-Look有Dynamic则通常情况下会显示Dynamic,除非Dynamic不可用或你明确告知系统显示Static。Dynamic需要绑定WKUserNotificationInterfaceController的子类,如未绑定则该Dynamic永远不会被显示。
Long-Look显示会触发以下方法进行布局:
- 本地通知
didReceiveLocalNotification:withCompletion: - 远程通知
didReceiveRemoteNotification:withCompletion:
界面布局完成后通过completionHandler方法参数控制Dynamic或Static
- WKUserNotificationInterfaceTypeCustom <-> Dynamic
- WKUserNotificationInterfaceTypeDefault <-> Static
参考代码:
// NotificationController.m
@implementation NotificationController
- (instancetype)init {
self = [super init];
if (self){
// 可在此处进行一些初始化操作
}
return self;
}
- (void)willActivate {
// 通知视图即将可见
[super willActivate];
}
- (void)didDeactivate {
// 通知视图已不可见
[super didDeactivate];
}
- (void)didReceiveLocalNotification:(UILocalNotification *)localNotification withCompletion:(void (^)(WKUserNotificationInterfaceType))completionHandler {
// 根据本地通知实例,在此处对Long-Look Dynamic界面布局
completionHandler(WKUserNotificationInterfaceTypeCustom);
}
- (void)didReceiveRemoteNotification:(NSDictionary *)remoteNotification withCompletion:(void (^)(WKUserNotificationInterfaceType))completionHandler {
// 根据远程通知内容,在此处对Long-Look Dynamic界面布局
completionHandler(WKUserNotificationInterfaceTypeCustom);
}
@end
Long-Look显示后
Watch App入口类未实例化时,会调用入口类的init和awakeWithContext:方法。
Long-Look界面以下动作都会调用DidDeactivate:
- 锁屏:30秒内点亮屏幕,依然是Long-Look界面;否则界面消失,可在“通知列表”中找到该通知;
- Back键:可在“通知列表”中找到该通知;
- “关闭”:从“通知列表”中清除该通知。
通知列表
点击通知会显示Long-Look界面,但只能显示Static界面不能再显示Dynamic界面。
自定义按钮(最多4个)
前台操作按钮:点击后WatchKit Extension启动并调用Watch app入口类的本地通知或远程通知方法。
// InterfaceController.m
@implementation InterfaceController
- (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)remoteNotification {
// 可根据Action的id和远程通知的内容进行处理
}
- (void)handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)localNotification {
// 可根据Action的id和本地通知的实例进行处理
}
@end
后台操作按钮:点击后WatchKit Extension不响应,直接调用相应iOS应用的方法,在后台进行处理。
// AppDelegate.m
@implementation AppDelegate
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void(^)())completionHandler {
// 可根据Action的id和本地通知的实例进行处理
completionHandler();
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler {
// 可根据Action的id和远程通知的内容进行处理
completionHandler();
}
@end