与安卓手机或者其他设备通信可以看我这篇文章。
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建立连接,产生通信