写在前面
WatchKit Apple提供的开发专题页面如下: https://developer.apple.com/watchkit/。其中包含两个Demo,这两个Demo可以让大家快速的了解WatchKit的构建。
Watch App Architecture
每一个Apple Watch App和 iOS Extension一样仍然需要依赖一个主体App,Apple Watch App 包含两个部分:Watch App 和 WatchKit Extension,如下图:
其中 Watch App 部分位于用户的Apple Watch上,它目前为止只允许包含Storyboard文件和Resources文件。在我们的项目里,这一部分不包括任何代码。
WatchKit Extension 部分位于用户的iPhone安装的对应App上,这里包括我们需要实现的代码逻辑和其他资源文件。
这两个部分之间就是通过 WatchKit
进行连接通讯。
WatchKit
WatchKit用来为开发者构建Apple Watch App。它所有的类如下,其中最上层的类继承于NSObject
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
WKInterfaceController WKUserNotificationInterfaceController WKInterfaceDevice WKInterfaceObject WKInterfaceButton WKInterfaceDate WKInterfaceGroup WKInterfaceImage WKInterfaceLabel WKInterfaceMap WKInterfaceSeparator WKInterfaceSlider WKInterfaceSwitch WKInterfaceTable WKInterfaceTimer |
WKInterfaceController
WKInterfaceController
是我们开发Watch App的核心类,它的地位和之前使用的UIViewController
一样。
每一个Watch App构建时,至少需要在Storyboard上设置一个WKInterfaceController
实例作为程序入口。我们可以在Storyboard上使用Main Entry Point
设置。
当用户launch了Watch App时,Watch OS 会开始加载程序中的Storyboard。我们在Storyboard中为每一个WKInterfaceController
设置的响应事件,会在用户触发时在WatchKit Extension中响应。我们可以像以前一样push, pop, present 目标WKInterfaceController
。
生命周期
WKInterfaceController
一样也有自己的生命周期,以下几个API对应了几个不同的状态:
1 2 3 |
- (instancetype)initWithContext:(id)context; - (void)willActivate; - (void)didDeactivate; |
当Watch OS加载App中的Storyboard时,iPhone端也会开始加载对应的WatchKit Extension。
当Watch OS开始初始化我们Watch App的Storyboard中的UI时,iPhone端WatchKit Extension会生成对应的WKInterfaceController
,并且响应initWithContext:
方法。
当Watch OS显示当前加载的UI时,WatchKit Extension中对应的WKInterfaceController
响应willActivate
方法。
当用户切换页面或者停止使用时,WatchKit Extension中对应的WKInterfaceController
响应didDeactivate
方法。
从上图可知这三个API,对应了Watch OS加载一个视图控制器的三个状态。我们在自己的WKInterfaceController
类中,应该实现这三个API用来处理不同的情况:
- initWithContext: 我们可以在这里加载数据或者更新在StoryBoard中当前Controller添加的interface objects。
- willActivate 我们可以在这里更新interface objects或者处理其他事件
- didDeactivate 我们应该在这里清理task或者数据。在这里更新interface objects将会被系统忽略。
页面跳转
当用户和我们的APP进行交互时,有很多时候,我们需要进行页面的跳转。WKInterfaceController
目前支持两组API进行页面跳转:
1 2 3 4 5 6 7 8 9 |
- (void)pushControllerWithName:(NSString *)name context:(id)context - (void)popController; - (void)popToRootController; - (void)presentControllerWithName:(NSString *)name context:(id)context; - (void)presentControllerWithNames:(NSArray *)names contexts:(NSArray *)contexts; - (void)dismissController; - (void)becomeCurrentPage; |
Push,Pop, Present, Dismiss的行为和UIViewController中类似。我们可以在代码中,根据程序上下文的状态,控制跳转到某一个页面。
使用这一组API时有四点需要注意:
- Push和Present方法第一个参数是对应的在Storyboard中为
WKInterfaceController
设置的identifier字符串。WatchKit Extension使用这几个API向Watch OS传递消息,真实的UI加载渲染行为是在Watch端进行。 - popToRootController是跳转到Watch App的Storyboard中
Main Entry Point
对应的Controller。 - presentControllerWithNames, 我们可以present一组Controller, 这一组Controller将以page control的形式展示。
- becomeCurrentPage 当页面是以page control的形式展现时,我们可以调用这个方法改变当前的page
另外一组API是:
1 2 3 4 |
- (id)contextForSegueWithIdentifier:(NSString *)segueIdentifier; - (NSArray *)contextsForSegueWithIdentifier:(NSString *)segueIdentifier; - (id)contextForSegueWithIdentifier:(NSString *)segueIdentifier inTable:(WKInterfaceTable *)table rowIndex:(NSInteger)rowIndex; - (NSArray *)contextsForSegueWithIdentifier:(NSString *)segueIdentifier inTable:(WKInterfaceTable *)table rowIndex:(NSInteger)rowIndex; |
当我们在应用设计的阶段就知道需要跳转的下一个WKInterfaceController
时,我们可以直接在Storyboard中设置Triggered Segues。使用Segues时,Selection同样支持Push和Model两种跳转方式。
我们可以使用上面一组API进行跳转中的数据传递。
响应交互事件
WKInterfaceObject中像Button,Slider, Switch等控件可以和用户交互,我们和往常一样,可以在WKInterfaceController
实现对应的Action,标记为IBAction,然后连接到Storyboard中。
这里特别的地方是,当我们的WKInterfaceController
中包含WKInterfaceTable
实例时,我们可以通过实现默认的- (void)table:(WKInterfaceTable *)table didSelectRowAtIndex:(NSInteger)rowIndex
方法响应table中每一行的点击事件,这里和往常的UITableView的实现方式不太一样,更加简单。
Glance
Glance是 Watch App上新的概念,它主要作用是给用户一个短时的提醒。我们可以通过Storyboard创建一个Glance interface Controller.对应的WatchKit Extension中,它同样需要继承于WKInterfaceController
,享有同样的生命周期。我们可以在其中实现自己的逻辑。
这里需要注意的是,Glance是可以和用户进行交互的。当用户Tap Glance页面时,会跳转到我们的Watch App中。这里可以在自定义的GlanceInterfaceController中使用- (void)updateUserActivity:(NSString *)type userInfo:(NSDictionary *)userInfo
传递数据。比如我们需要在用户点击Glance之后进入到某一个特定的页面,我们可以把目标页面的identifier和要传递的其他消息包装到字典中,然后在Initial Interface Controller中实现- (NSString *)actionForUserActivity:(NSDictionary *)userActivity context:(id *)context
方法跳转到目标页面,这里的userActivity就是上文传递的userInfo,返回的NSString是目标页面的identifier,context指针是目标页面initWithContext
中context数据。
Notification && WKUserNotificationInterfaceController
当我们的主体App支持Notification时,Apple Watch将能够显示这些通知。Watch OS提供了默认的通知显示,当用户点击通知进入我们的App时,Initial Interface Controller中- (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)remoteNotification
或者- (void)handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)localNotification
方法将会被响应,我们可以通过实现这两个方法获得通知的消息,跳转到目标页面。
我们同样可以通过Storyboard创建一个Notification interface Controller,这样可以实现自定义的通知界面。对应的WatchKit Extension中,它继承于WKUserNotificationInterfaceController
,享有和WKInterfaceController
同样的生命周期。我们可以通过实现下面两组API- (void)didReceiveRemoteNotification:(NSDictionary *)remoteNotification withCompletion:(void(^)(WKUserNotificationInterfaceType interface)) completionHandler
或者- (void)didReceiveLocalNotification:(UILocalNotification *)localNotification withCompletion:(void(^)(WKUserNotificationInterfaceType interface)) completionHandler
获得通知内容,并设置处理完成的回调Block。
Menu
我们可以通过Storyboard在界面中添加Menu,它看起来像这样:
我们不但可以通过Storyboard在Menu中添加Item,也可以通过WKInterfaceController
中以下一组API,在上下文环境中添加相应的Item:
1 2 3 4 |
- (void)addMenuItemWithImage:(UIImage *)image title:(NSString *span class="crayon-o">:(UIImage *)image title:(NSString *ػ体App,Apple Watch App 包含两个部分:Watch App 和 WatchKit Extension,如下图:
其中 Watch App 部分位于用户的Apple Watch上,它目前为止只允许包含Storyboard文件和Resources文件。 WatchKit Extension 部分位于用户的iPhone安装的对应App上,这里包括我们需要实现的代码逻辑和其他资源文件。 这两个部分之间就是通过 WatchKitWatchKit用来为开发者构建Apple Watch App。它所有的类如下,其中最上层的类继承于
WKInterfaceController
每一个Watch App构建时,至少需要在Storyboard上设置一个 当用户launch了Watch App时,Watch OS 会开始加载程序中的Storyboard。我们在Storyboard中为每一个 生命周期
当Watch OS加载App中的Storyboard时,iPhone端也会开始加载对应的WatchKit Extension。 当Watch OS开始初始化我们Watch App的Storyboard中的UI时,iPhone端WatchKit Extension会生成对应的 当Watch OS显示当前加载的UI时,WatchKit Extension中对应的 当用户切换页面或者停止使用时,WatchKit Extension中对应的 从上图可知这三个API,对应了Watch OS加载一个视图控制器的三个状态。我们在自己的
页面跳转当用户和我们的APP进行交互时,有很多时候,我们需要进行页面的跳转。
Push,Pop, Present, Dismiss的行为和UIViewController中类似。我们可以在代码中,根据程序上下文的状态,控制跳转到某一个页面。 使用这一组API时有四点需要注意:
另外一组API是:
当我们在应用设计的阶段就知道需要跳转的下一个 我们可以使用上面一组API进行跳转中的数据传递。 响应交互事件WKInterfaceObject中像Button,Slider, Switch等控件可以和用户交互,我们和往常一样,可以在 这里特别的地方是,当我们的 GlanceGlance是 Watch App上新的概念,它主要作用是给用户一个短时的提醒。我们可以通过Storyboard创建一个Glance interface Controller.对应的WatchKit Extension中,它同样需要继承于 这里需要注意的是,Glance是可以和用户进行交互的。当用户Tap Glance页面时,会跳转到我们的Watch App中。这里可以在自定义的GlanceInterfaceController中使用 Notification && WKUserNotificationInterfaceController当我们的主体App支持Notification时,Apple Watch将能够显示这些通知。Watch OS提供了默认的通知显示,当用户点击通知进入我们的App时,Initial Interface Controller中 我们同样可以通过Storyboard创建一个Notification interface Controller,这样可以实现自定义的通知界面。对应的WatchKit Extension中,它继承于 Menu我们可以通过Storyboard在界面中添加Menu,它看起来像这样: 我们不但可以通过Storyboard在Menu中添加Item,也可以通过 |