数据交互详解
watchos 1 时,watch app 与 iPhone app 交互使用 app group, 但是在2上不能使用app group 了,因为watchos2已经不再是iPhone的附属,而是作为独立的OS设备存在,类似于两台独立的iPhone一样,不能像在同一在机器上使用app group来共享数据。
WatchOS 2 提供了Watch Connectivity framework来进行经过配对的watch 和 iphone的数据交换,该框架可以后台传输和前台传输。
WatchConnectivity framewor提供了一个WCSession对象,我们要通过WCSession可以进行数据传输。
1建立WCSession
在watch extention端和iphone端都要先建立默认WCSession对象,指定委托委托,并加以激活。
Objective-C
if ([WCSessionisSupported]) {
WCSession* session= [WCSession defaultSession];
session.delegate= self;
[session activateSession];
}
Swift
if WCSession.isSupported() {
let session = WCSession.defaultSession()
session.delegate= self
session.activateSession()
}
2连接状态
2.1判断连接状态
在传输数据时需要判断watch 和 iphone的连接状态,wcsesson属性里提供了如下状态:已经配对(paired)、watch应用已经安装(watchAppInstalled)、两者连接相通(reachable)。当watch已经配对且watch端应用安装好时,可以进行后台传输数据;当两者连接相通时,可以直接进行前台传输。
2.2连接状态改变回调
指定委托后,就可以在连接状态改变时做出相对反应。
当配对或应用安装发生变化时(paired or watchAppInstalled),会调用sessionWatchStateDidChange:method。
当即时连接变化时(reachable),会调用sessionReachabilityDidChange:method。
我们要根据需要自己在指定的委托中添加上述需要处理的函数。
3数据传输
3.1覆盖式后台传输
后台传输就是说不是数据立刻传输,而是当具备数据传输连接条件以后,watch和iphone之间自动同步数据,也就输说后台传输的数据是异步传输,具有延后性。
当第一发送的数据海没有传送出去,如果此时进行第二次数据传输,会覆盖第一次的数据,所以真正传输的是第二次的数据,第一次的数据会丢失。
(1) 发送数据
发送数据使用updateApplicationContext函数:
Declaration
Swift
func updateApplicationContext(_applicationContext: [String : AnyObject]) throws
Objective-C
-(BOOL)updateApplicationContext:(NSDictionary<NSString *,id>*)applicationContext error:(NSError *_Nullable *)error
/***
Parameters
applicationContext
A dictionary of property list values. Youdefine the meaning of the dictionary contents. This parameter must not be nil.
error
On input, a pointer to an error object. Onoutput, the pointer is set to an error object if a problem occurred. You mayspecify nil if you do not care about error information.
***/
可见,发送的是一个字典数据(dictionary)。
(2) 接收数据
数据传输是后台异步的,当接收完毕时会调用委托的didReceiveFile函数,如果需要立即处理后台传输的数据,那么我们可以调用改函数。
接收的数据会放在WCSession的receivedApplicationContext属性中,我们在需要时读取该属性即可。
SWIFT
var receivedApplicationContext: [String : AnyObject] { get }
OBJECTIVE-C
@property(nonatomic,readonly, copy) NSDictionary<NSString *,id> *receivedApplicationContext
3.2队列式后台传输
(1)发送数据
队列式后台传输,后一次的数据不会覆盖前一次的数据,而是把所有的数据按照次序全部发送出去。也是发送字典数据,是个大量数据传输。
队列时发送字典数据函数:transferUserInfo声明:
Swift
func transferUserInfo(_ userInfo: [String :AnyObject]) -> WCSessionUserInfoTransfer
Objective-C
- (WCSessionUserInfoTransfer*)transferUserInfo:(NSDictionary<NSString *,id> *)userInfo
/***
Parameters
userInfo
A dictionary of property list values thatyou want to send. You define the contents of the dictionary that yourcounterpart supports. This parameter must not be nil.
Return Value
A transfer object that you can use tomonitor and cancel the operation.
**/
(2)接收数据
接收端会把数据存放在WCSession的WCSessionUserInfoTransfer属性中,但是我们不能直接读取,需要获取函数outstandingUserInfoTransfers来获取。
SWIFT
var outstandingUserInfoTransfers:[WCSessionUserInfoTransfer] { get }
OBJECTIVE-C
@property(nonatomic, readonly, copy)NSArray <WCSessionUserInfoTransfer *> *outstandingUserInfoTransfers
3.3 文件传输
(1)发送文件
发送文件也是后台模式。
发送文件函数transferFile:metadata:声明如下:
Swift
func transferFile(_ file: NSURL,metadata metadata: [String : AnyObject]?) -> WCSessionFileTransfer
Objective-C
- (WCSessionFileTransfer*)transferFile:(NSURL *)file metadata:(NSDictionary<NSString *,*)metadata
/***
Parameters
file
A file-based URL that identifies the fileto send. The specified file must be readable by the current app. This parametermust not be nil.
metadata
An optional dictionary containingadditional data to send. The values of the dictionary must all be property listobject types. You may specify nil for this parameter.
Return Value
A file transfer object containing the fileand dictionary being sent. You can use this object to cancel the file transferat a later time.
**/
(2)接收文件
接收文件后存放在WCSessionFileTransfer中,通过如下函数获取:
SWIFT
var outstandingFileTransfers:[WCSessionFileTransfer] { get }
OBJECTIVE-C
@property(nonatomic, readonly, copy)NSArray <WCSessionFileTransfer *> *outstandingFileTransfers
(3)文件处理
在接到一个文件后,会调用委托函数session:didReceiveFile:,处理文件代码就要写在改函数中。需要强调的是,如果在该函数中找另外一个地方来保存收到的文件,那么这个文件会被删除,不再存放在WCSessionFileTransfer,因为WCSessionFileTransfer只有一个,要用于接收下一个收到文件。
4前台数据传输
前台数据传输只有一种模式,那就是发送即时消息
(1) 发送消息
发送消息函数sendMessage:replyHandler:errorHandler:声明
Swift
func sendMessage(_message: [String : AnyObject],replyHandlerreplyHandler:(([String : AnyObject]) -> Void)?, errorHandlererrorHandler:((NSError) -> Void)?)
Objective-C
- (void)sendMessage:(NSDictionary<NSString *id>*)message replyHandler:(void(^)(NSDictionary<NSString *id>*replyMessage))replyHandler errorHandler:(void(^)(NSError *error))errorHandler
/***
Parameters
message
A dictionary of property list values thatyou want to send. You define the contents of the dictionary that yourcounterpart supports. This parameter must not benil.
replyHandler
A reply handler for receiving a responsefrom the counterpart. Specifynil if you do not want to receive a reply.This block has no return value and takes the following parameter:
replyMessage
A dictionary of property list values containing the response from the counterpart.
errorHandler
A block that is executed when an erroroccurs. Specifynil if you do not care about error information. This block has no returnvalue and takes the following parameter:
errorHandler
An error object containing the reason for the failure. When sending messages, the most common error is that the paired device was not reachable, but other errors may occur too.
***/
这是一个异步函数,发送消息到消息队列,不会覆盖之前的消息。
如果需要处理回答消息,则可用replyHandler来处理replyMessage。
从watch端调用sendMessage,会唤醒iphone端对应的应用,reachable为真;但是从iphone端调用sendMessage,不能唤醒watch端对应的应用,不改变reachable。所以发送消息时请确保watch和iphone时正常连接,且watch打开应用。若果发送消息失败,则调用errorHandler。
(2) 接收消息
接收消息时会出发托管session:didReceiveMessage:,声明如下:
optional func session(_ session: WCSession,didReceiveMessage message: [String : AnyObject])
OBJECTIVE-C
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString* id> *)message
/***
Parameters
session
The session object that received themessage from its counterpart.
message
A dictionary of property list valuesrepresenting the contents of the message. Use the contents of this dictionaryto determine what course of action to take.
***/
上述message就是我们收到的消息,在didReceiveMessage中处理即可。
(3) 收发数据消息
上面涉及的是比较短的消息,而watchos2 还可发送内容较多的数据消息,使用方法参照上面的didReceiveMessage,只不过函数改为
session:didReceiveMessage:replyHandler:发数据消息
session:didReceiveMessage:replyHandler:收数据消息