iOS-AppleWatch与iOS应用之间的通信

与安卓手机或者其他设备通信可以看我这篇文章

官方文档:

Ensure Your App Runs Independently

Independent apps must function without relying on a companion iOS app. This functionality includes performing tasks like downloading data, setting up the user’s account, or configuring the app.

Specifically, an independent watchOS app must:

  • Let users sign in and create new accounts on Apple Watch. For more information, see Authenticating Users on Apple Watch.
  • Request permission on the watch for any system services that it requires. Users should never need to authorize an app on their iPhone. For example, in watchOS 6 and later, apps that use HealthKit can request user authorization on Apple Watch.
  • Download data directly to the watch. Independent apps can’t rely on WatchConnectivity to transfer data or files from an iOS companion app. If you need to sync data between devices, consider using CloudKit, or syncing through your own server. For more information, see Keeping Your watchOS Content Up to Date.
  • Send push notifications, including complication pushes, directly to the watch. For more information, see registerForRemoteNotifications.

An independent app can use WatchConnectivity to transfer information from its iOS companion app when the iOS device is available. However, the independent app can’t use WatchConnectivity as its main source of data, and must be capable of accessing information on its own.

Framework :

[图片上传失败...(image-35fb99-1594777551415)]

WatchConnectivity.h没有实质的内容,里面包含了WatchConnectivity.framework中所有 interface 文件。
WCDefines.h里面包含了一些宏定义,我们一般不用关注。
WCError.h里面包含了一些错误信息的定义,我们在iPhone与Apple Watch 通信过程中报错的错误信息都会与之一一对应。
WCSession.h是WatchConnectivity.framework的核心部分,我们想实现iPhone与Apple Watch 通信该interface是重点了解。
WCSessionFile.h是iPhone与Apple Watch 通信过程中传输File的相关信息,可以通过WCSessionFile查到传输文件的相关信息。
WCSessionUserInfoTransfer.h用于跟踪正在传输的userInfo字典信息。

  • 关于WCSession
    WCSession.h 提供interface方法主要分为四类:
     第一类: WCSession对象相关。
     第二类: iOS App 监听 Watch App 状态。
     第三类: 数据传输(消息互动、后台传输)。
     第四类: WCSession的相关代理。
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@class WCSessionFile, WCSessionFileTransfer, WCSessionUserInfoTransfer;
@protocol WCSessionDelegate;

typedef NS_ENUM(NSInteger, WCSessionActivationState) {
    WCSessionActivationStateNotActivated  = 0,
    WCSessionActivationStateInactive      = 1,
    WCSessionActivationStateActivated     = 2,
} __IOS_AVAILABLE(9.3) __WATCHOS_AVAILABLE(2.2);

/* -------------------------------- WCSession对象相关 ---------------------------------*/
NS_CLASS_AVAILABLE_IOS(9.0)
@interface WCSession : NSObject

/** 检查该iOS设备是否支持会话。在WatchOS上会话是一定可用的。 */
+ (BOOL)isSupported;

/** 默认的会话 */
@property (class, readonly) WCSession *defaultSession;

/** 初始化方法;用 defaultSession ,不要使用该方法*/
- (instancetype)init NS_UNAVAILABLE;

/** 会话代理 */
@property (nonatomic, weak, nullable) id <WCSessionDelegate> delegate;

/** 激活会话*/
- (void)activateSession;

/** 当前会话状态 */
@property (nonatomic, readonly) WCSessionActivationState activationState __IOS_AVAILABLE(9.3) __WATCHOS_AVAILABLE(2.2);

/** 会话是否有更多的内容*/
@property (nonatomic, readonly) BOOL hasContentPending __IOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0);

/** ------------------------- iOS App 监听 Watch App 状态 ---------------------------*/
/** 检查iOS设备是否与手表配对 */
@property (nonatomic, readonly, getter=isPaired) BOOL paired __WATCHOS_UNAVAILABLE;

/** 检查用户是否安装了手表应用程序 */
@property (nonatomic, readonly, getter=isWatchAppInstalled) BOOL watchAppInstalled __WATCHOS_UNAVAILABLE;

/** 检查用户是否启用了手表应用程序的并发性 */
@property (nonatomic, readonly, getter=isComplicationEnabled) BOOL complicationEnabled __WATCHOS_UNAVAILABLE;

/** The number of calls remaining to 
transferCurrentComplicationUserInfo: before the system starts 
transferring the complicationUserInfo as regular userInfos. If this is 
0, the complicationUserInfo will be transferred as regular 
userInfos. Count will be 0 whenever the complication is not 
enabled */
@property (nonatomic, readonly) NSUInteger remainingComplicationUserInfoTransfers __IOS_AVAILABLE(10.0) __WATCHOS_UNAVAILABLE;

/** Use this directory to persist any data specific to the selected 
Watch. The location of the URL will change when the selected 
Watch changes. This directory will be deleted upon next launch if 
the watch app is uninstalled for the selected Watch, or that Watch 
is unpaired. If the watch app is not installed for the selected Watch 
the value will be nil. */
@property (nonatomic, readonly, nullable) NSURL *watchDirectoryURL __WATCHOS_UNAVAILABLE;



/** -------------------------- 消息互动 ---------------------------
 *  只能在两个正在运行的应用程序之间发送。
 *  要求相应的应用程序可以访问。
 */

/** 对应的应用程序必须是可访问的,以便发送消息成功 */
@property (nonatomic, readonly, getter=isReachable) BOOL reachable;

/** 在Watch应用程序中,可达性要求配对的iOS设备在重启后至少
解锁一次。这个属性可以用来确定iOS设备是否需要解锁。如果可
访问属性设置为NO,可能是因为iOS设备重新启动,需要解锁。如
果是这样的话,手表可以提示用户打开他们的配对的iOS设备。 */
@property (nonatomic, readonly) BOOL iOSDeviceNeedsUnlockAfterRebootForReachability __IOS_UNAVAILABLE __WATCHOS_AVAILABLE(2.0);

/** 客户端可以使用此方法将消息发送到对应的应用程序。希望接收
特定消息的客户端应该通过一个replyHandler块。如果无法发送消
息,或者无法接收到应答,则将使用错误来调用errorHandler块。
如果指定了replyHandler和errorHandler,那么将会调用其中的一
个。消息只能在发送应用程序运行时发送。如果在发送消息之前发
送应用程序退出,发送将失败。如果对应的应用程序没有运行,对
应的应用程序将会在接收到消息时启动(iOS对应的应用程序)。 */
- (void)sendMessage:(NSDictionary<NSString *, id> *)message replyHandler:(nullable void (^)(NSDictionary<NSString *, id> *replyMessage))replyHandler errorHandler:(nullable void (^)(NSError *error))errorHandler;

- (void)sendMessageData:(NSData *)data replyHandler:(nullable void (^)(NSData *replyMessageData))replyHandler errorHandler:(nullable void (^)(NSError *error))errorHandler;


/** --------------------------- 后台传输 ---------------------------
 *  后台传输在发送应用程序退出时继续传输。对应的应用程序(另
一侧)不需要运行后台传输才能继续。系统将在适当的时候转移内容。
 */

/** 设置applicationContext是一种传输应用程序的最新状态的方
法。在更新applicationContext后,系统在适当的时间启动数据传
输,在应用程序退出后可以进行数据传输。如果应用程序上下文成
功到达,对应的应用程序将在下一次启动时接收一个委托回调。如
果没有应用程序上下文,它应该用一个空字典更新。applicationContext字典只能接受属性列表类型 */
@property (nonatomic, readonly, copy) NSDictionary<NSString *, id> *applicationContext;
- (BOOL)updateApplicationContext:(NSDictionary<NSString *, id> *)applicationContext error:(NSError **)error;

/** 将最近收到的应用程序上下文存储在对应的应用程序中 */
@property (nonatomic, readonly, copy) NSDictionary<NSString *, id> *receivedApplicationContext;

/** 该系统将对用户信息字典进行排队,并在适当的时候将其传输到
对应的应用程序。在发送应用程序退出后,用户信息的传输将继
续。如果文件成功到达,对应的应用程序将在下一次启动时接收一
个委托回调。userInfo字典只能接受属性列表类型。
 */
- (WCSessionUserInfoTransfer *)transferUserInfo:(NSDictionary<NSString *, id> *)userInfo;

/** Enqueues a user info dictionary containing the most current 
information for an enabled complication. If the app's complication 
is enabled the system will try to transfer this user info immediately. 
Once a current complication user info is received the system will 
launch the Watch App Extension in the background and allow it to 
update the complication content. If the current user info cannot be 
transferred (i.e. devices disconnected, out of background launch 
budget, etc.) it will wait in the outstandingUserInfoTransfers queue 
until next opportune time. There can only be one current 
complication user info in the outstandingUserInfoTransfers queue. 
If a current complication user info is outstanding (waiting to 
transfer) and -transferCurrentComplicationUserInfo: is called again 
with new user info, the new user info will be tagged as current and 
the previously current user info will be untagged. The previous 
user info will however stay in the queue of outstanding transfers. */
- (WCSessionUserInfoTransfer *)transferCurrentComplicationUserInfo:(NSDictionary<NSString *, id> *)userInfo __WATCHOS_UNAVAILABLE;

/** 返回仍在传输的用户信息传输的数组(例如,未被取消、失败或被对应应用程序接收)。*/
@property (nonatomic, readonly, copy) NSArray<WCSessionUserInfoTransfer *> *outstandingUserInfoTransfers;

/** 系统会在适当的时候对文件进行排队,并将其传输到对应的应用
程序。在发送应用程序退出后,文件的传输将继续。如果文件成功
到达,对应的应用程序将在下一次启动时接收一个委托回调。元数
据字典只能接受属性列表类型 */
- (WCSessionFileTransfer *)transferFile:(NSURL *)file metadata:(nullable NSDictionary<NSString *, id> *)metadata;

/** 返回仍在传输的文件传输数组(例如,未被取消、失败或被对应应用程序接收)。*/
@property (nonatomic, readonly, copy) NSArray<WCSessionFileTransfer *> *outstandingFileTransfers;

@end


/** ----------------------------- WCSessionDelegate -----------------------------*/
@protocol WCSessionDelegate <NSObject>

/** 当会话完成激活时调用。如果会话状态是WCSessionActivationStateNotActivated,则会有更多的细节错误。 */
- (void)session:(WCSession *)session activationDidCompleteWithState:(WCSessionActivationState)activationState error:(nullable NSError *)error __IOS_AVAILABLE(9.3) __WATCHOS_AVAILABLE(2.2);

/** ------------------------- iOS App State For Watch ------------------------ */

/** 当会话不能再用于修改或添加任何新的传输时,所有交互消息都
将被取消,但是仍然会发生后台传输的委派回调。当选择的表被更
改时,就会发生这种情况。*/
- (void)sessionDidBecomeInactive:(WCSession *)session __IOS_AVAILABLE(9.3) __WATCHOS_UNAVAILABLE;

/** session 已经 禁用
Called when all delegate callbacks for the previously selected 
watch has occurred. The session can be re-activated for the now 
selected watch using activateSession. */
- (void)sessionDidDeactivate:(WCSession *)session __IOS_AVAILABLE(9.3) __WATCHOS_UNAVAILABLE;

@optional

/** 手表状态已经改变回调 */
- (void)sessionWatchStateDidChange:(WCSession *)session __WATCHOS_UNAVAILABLE;

/** ------------------------- Interactive Messaging ------------------------- */

/** 当对应的应用程序的可到达状态改变时调用。接收方应在接收此委托回调时检查可访问属性 */
- (void)sessionReachabilityDidChange:(WCSession *)session;

/**已经接收到消息 
Called on the delegate of the receiver. Will be called on startup if 
the incoming message caused the receiver to launch. */
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *, id> *)message;

/**已经接收到消息  
Called on the delegate of the receiver when the sender sends a 
message that expects a reply. Will be called on startup if the 
incoming message caused the receiver to launch. */
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *, id> *)message replyHandler:(void(^)(NSDictionary<NSString *, id> *replyMessage))replyHandler;

/** 已经接收到消息  
Called on the delegate of the receiver. Will be called on startup if 
the incoming message data caused the receiver to launch. */
- (void)session:(WCSession *)session didReceiveMessageData:(NSData *)messageData;

/** 已经接收到消息  
Called on the delegate of the receiver when the sender sends 
message data that expects a reply. Will be called on startup if the 
incoming message data caused the receiver to launch. */
- (void)session:(WCSession *)session didReceiveMessageData:(NSData *)messageData replyHandler:(void(^)(NSData *replyMessageData))replyHandler;


/** -------------------------- Background Transfers ------------------------- */

/** 如果应用程序上下文可用,将在启动时调用。 */
- (void)session:(WCSession *)session didReceiveApplicationContext:(NSDictionary<NSString *, id> *)applicationContext;

/** 在用户信息传递成功完成或失败后,调用发送方。当用户信息完成时,如果发送者没有运行,将被调用下一次启动。 */
- (void)session:(WCSession * __nonnull)session didFinishUserInfoTransfer:(WCSessionUserInfoTransfer *)userInfoTransfer error:(nullable NSError *)error;

/** 如果用户信息在接收者没有运行时完成传输,将在启动时调用。 */
- (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary<NSString *, id> *)userInfo;

/** 已经完成文件传输 
Called on the sending side after the file transfer has successfully 
completed or failed with an error. Will be called on next launch if 
the sender was not running when the transfer finished. */
- (void)session:(WCSession *)session didFinishFileTransfer:(WCSessionFileTransfer *)fileTransfer error:(nullable NSError *)error;

/** 已经接收到的文件
Called on the delegate of the receiver. Will be called on startup if 
the file finished transferring when the receiver was not running. 
The incoming file will be located in the Documents/Inbox/ folder 
when being delivered. The receiver must take ownership of the file 
by moving it to another location. The system will remove any 
content that has not been moved when this delegate method 
returns. */
- (void)session:(WCSession *)session didReceiveFile:(WCSessionFile *)file;


@end

NS_ASSUME_NONNULL_END

通信机制:

(1)用户需要开启蓝牙连接Watch后在APP中进行设置,调整手表与iPhone的交互关系,蓝牙距离9米,超过距离,断开连接

(2)iPhone 与AppleWatch处于同一Wi-Fi网络(或者连接到由iPhone建立的Wi-Fi热点),只要信号存在,双方距离多远都可以

(3)watch应用对象添加到项目后,包含Watch App 和 WatchKit Extension。Watch App 位于iWatch上,目前只允许包含storyboard 和 Resource文件;Watch Extension 位于用户的iPhone安装的对应App上,这里包括我们需要实现的代码逻辑和其他资源。这两部分通过Watch Kit进行连接通讯,用户点击Watch App后,与Watch匹配的iPhone会启动WatchKit extension,然后和Watch建立连接,产生通信

参考文献:

Apple Watch的通信机制

iOS 和 iWatch之间的通讯方式

//www.greatytc.com/p/556d9bed5057

watchOS 笔记

构建AppleWatch应用(iOS App与WatchKit Extension的数据通信)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349