Apple Watch之watch app开发知识点 (通信部分
开发watch app的相关资料
说实话,基本上没有什么现成的资料。apple watch实在是很小众的东西,远不如iPhone那么普及,想开发一款完整的watch app能找到的资料实在是很少,想开发还是得去看看苹果给的英文文档。当然,如果你的需求不是比较复杂,可能仅有的那么一点中文资料就足够了。但是,如果你的app是和运动相关,可能就比较复杂了。言归正传,下面将讲一些在app中会用到的东西,可能面对的一些问题。
watch app与iOS app通信
https://www.natashatherobot.com/watchconnectivity-say-hello-to-wcsession/ 这是外国人写的,国内已经有人翻译,而且在网上基本上搜的都是这篇,强烈建议先看下这个Demo,顺便查下资料,了解一些基本知识点儿。在这里只是根据实际开发情况进行补充,对踩过的一些坑进行总结。
首先,解释下为什么需要有个“WatchSessionManager”单例来专门用来通信。一般来说,如果在做iOS app时,如果不是需要长链接的话,比如说http/https请求,对一个控制器而言,网络请求都是在移动端主动发起,是移动端向服务器去拿数据展示,或者向服务器上传数据,主动权都是在客户端,干完事儿了,服务器与客服端就断开了。当然长链接的话就不是这样的情况了,有可能出现客户端是被动接受信息,比如说账户被挤下线,就是长链接状态下,另一台手机登录了你的账号,也许你的手机并没有做什么请求网络的动作,而你还是下线了,这是因为服务器与你的手机一直保持长链接状态并没有断开,这时服务器可以随时向你手机发送消息,从而让你下线。同理,在开发watch app时会发现,基本上watch app除了主动发起通信,还会被动接受通信,在iOS app端同理,总之一句话,就是互相控制。如果用过CocoaAsyncSocket的话,这些自然了解,而且“WatchSessionManager”可以说就是写个watch版的CocoaAsyncSocket。用WatchSessionManager来统管网络通信部分,控制器只是其代理,用来接收WatchSessionManager传来的数据。
言归正传,“WatchSessionManager”有两个,一个写在iOS app中,另一个写在watch app中,Apple watch和iphone之间的通信靠的就是它们两个,而且,其中完成通信的核心部分是“WCSession”(见图三),以私有成员变量的形式,分别存在于两个“WatchSessionManager”中,要注意的是,虽说都是“WCSession”,但是,一个是在iOS app 中,另一个是在watch app中,硬件环境不同,注定了就算大部分方法和成员变量是相同的,但仍有一些方法或者成员变量是不同的,这些点在外国人的Demo中表现的并不是很明显,看他的代码要是不熟悉基本知识,会有些云里雾里。
在iOS app中的“WatchSessionManager”,图一 在watch app中的“WatchSessionManager”,图二 在iOS app中的“WatchSessionManager”部分代码,图三最常用方法:
通信中,最常用的代理方法:open func sendMessage(_message: [String:Any], replyHandler: (([String:Any]) -> Swift.Void)?, errorHandler: ((Error) -> Swift.Void)? =nil) 和 open func sendMessageData(_data:Data, replyHandler: ((Data) -> Swift.Void)?, errorHandler: ((Error) -> Swift.Void)? =nil)
贴一段在watch app中“WatchSessionManager”的方法
watch向iphone发送信息的方法,图四在该方法中,我使用的是WCSession实例方法中有replyHandler这个参数的方法(open func sendMessage(_message: [String:Any], replyHandler: (([String:Any]) -> Swift.Void)?, errorHandler: ((Error) -> Swift.Void)? =nil))来发送信息到手机(即iOS app),从该方法可以看出,传递的信息是字典的形式存在,例如参数message和replyHandler,所以,图中可以看到requestValues是以字典的形式传送到手机上。有发信息就有收信息,在iOS app中的“WatchSessionManager”实现了“WCSession”的代理方法:public func session(_session:WCSession, didReceiveMessage message: [String:Any], replyHandler:@escaping([String:Any]) ->Swift.Void),来处理watch发来的消息。要注意的是,在实现该方法时,最好要调用叫做replyHandler的block,虽然不一定要调用,但是这个block可以方便“响应”请求,以简洁的代码返回消息,如果不是调用这个block,你就得自己再在iOS app端调用“WCSession”的发送消息的方法来“响应”请求,这个相对而言就麻烦了些,而且,不调用这个block,是会报超时错误的,但不会崩溃。
其他常用方法:
“WCSession”实例的:open func updateApplicationContext(_applicationContext: [String:Any])throws
在实际开发中,需要手机向手表发送图片,让图片在手表上显示出来,最开始还是使用上文中最常用的方法,但是发现有的图片传不过来,控制台打印出“负载过大”,去网上搜了下,有国外的大神回答了过该问题,答案是“sendMessage:the size limit (iOS 9) is 65.5 kB,The size limit for updateApplicationContext is 262 kB.”,最常用的方法最多只能传65.5kB的数据,而updateApplicationContext则能传262kB的数据,图片很容易就超过100kB了,所以果断换成了在iOS app中使用updateApplicationContext来传送图片到watch。
在“WatchSessionManager”的扩展中,实现了“updateApplicationContext”,图五使用updateApplicationContext还有一个原因是,当iOS app被手动杀死时,我们需要在watch app中做一些保存或者退出的业务,这个时候,最常用方法也是不起作用的,而updateApplicationContext是支持iOS app被杀死时,向watch app发送消息。首先,在iOS app中注册通知
监听iOS app被杀死的通知,图六监听到通知时调用的方法
通知对应的方法,图七在watch app中接收信息的方法,
接收消息的方法,图八写得好累,暂时就写在这里,之后还会有其他知识点陆续放出。第一次写博客,不好的地方,尽管喷,我虚心接收,激励我越写越好。