先看看要实现的效果
2016-05-12 22.27.44.gif第一步:打开Xcode 新建一个Apple Watch项目或者为已有项目添加Apple Watch支持
新建一个Apple Watch项目
新建一个Apple Watch项目.png已有项目添加Apple Watch支持
为已有项目添加Apple Watch支持.png第二步:如何实现Apple Watch和iOS app之间的通信
Apple Watch和iOS app之间的通讯使用WCSession
类,在iOS App端
- 导入头文件
#import <WatchConnectivity/WatchConnectivity.h>
- 配置WCSession会话
self.session = [WCSession defaultSession];
self.session.delegate = self;
//* 必须激活session */
[self.session activateSession];
遵守WCSessionDelegate
协议并实现session: didFinishUserInfoTransfer: error:
方法,查看Apple Watch端和iOS端是否存在配对失败或者WCSession会话未激活等错误信息。
- iOS端发送消息给Apple Watch端(两种常用方法(1,2))
- 使用
transferCurrentComplicationUserInfo
这种只能传NSDictionary
- 使用
sendMessage: replyHandler: errorHandler:
或者sendMessageData: replyHandler: errorHandler:
,前面一种也是只能传NSDictionary
,后面一种看方法都知道要传的是一个NSData
- 使用
transferFile: metadata:
还能传文件
可见WCSession真的很强大 - 接收iOS端发送的消息(在Apple Watch端
InterfaceController.m
文件)
跟在iOS端一样,配置WCSession
会话,遵守WCSessionDelegate
协议并实现session: didReceiveUserInfo:
接收iOS端发送过来的数据。上面提到了有好几种方法可以发送消息给Apple Watch端,那么对应的就有好几种接受数据的方法。
transferCurrentComplicationUserInfo
对应的接收数据方法session: didReceiveUserInfo:
sendMessage: replyHandler: errorHandler:
对应的接收数据方法session: didReceiveMessage:
sendMessageData: replyHandler: errorHandler:
对应的接收数据方法session: didReceiveMessageData:
transferFile: metadata
对应的接收数据方法session: didReceiveFile:
注意WCSessionDelegate
协议的函数默认在子线程执行,如果是更新UI的话在子线程接收数据然后显示到UI上会有12s-20s
之间不等的延迟。
第三步:Apple Watch的tableView如何自定义Cell
其实在Apple Watch上面开发比在iOS App端开发简单多了。
在Apple Watch上面所有界面布局全部使用storyboard
布局,没有所谓的纯代码
或者Xib
布局,不信你看下图,这也充分说明了Apple推荐我们使用storyboard
来进行布局
在Apple Watch上面所有
class
不管是不是控件都是继承至NSObject
,而且都是使用set
方法
进入正题:进入Interface.storyboard
,找到Interface Controller Scene
这个界面就是我们看到的第一个界面。
拖一个table
到Interface Controller Scene
里面,你会发现它会自动的跑到顶部,不管你放到哪个位置。这个问题等会儿下面会讲。细心的人可能还会发现table下面是一个Row Controller
而不是和iOS App那样是一个Cell
iOS App TableView.png
展开
Table Row Controller
,他下面是一个Group
这个Group和iOS App里面Cell下面的Content View
其实是一个东西,容器嘛,只是换了一个叫法而已,不再是UIView。Group.png
如果做过iOS App开发的同学都知道tableViewCell的重用机制需要设置一个
identifier
,同理,这里也需要设置identifier,点击Table Row Controller
在右侧第4个检查器设置identifier
布局:布局可谓是尤为重要的一部分,UI可以决定一个app的生死。
在开头gif的效果图中可以看到里面table里面只有三个元素,一个image显示图片,两个label分别显示昵称和内容。既然是这样,那就直接把拖一个image和两个label进去。这时候你会发现你拖一个image进入之后就直接填充满了整个Group
,你会以为这跟StackView
是一样的,再拖一个控件进去就会自动修改image的width,然而,并不是这样。
在Apple Watch里面每个控件的Alignment
方式,Horizontal
默认是Left
,Vertical
默认是Top
,这也是为什么刚开始就说拖一个控件到Interface Controller Scene
里面,不管在什么位置都会自己跑到顶部的原因。
既然知道是什么原因了,那就改吧。点击image,在右侧第4个检查器改Size
,
第一个是说根据内容大小调整宽高
第二个是说相对于父容器来说的一个比例
第三个是说给定一个固定的宽高
我使用的是第二个,相对于父容器的一个比例
Width
为0.25
,Height
为0.8
,然后修改Vertical
为center
再继续,label,拖进去之后修改label的
Width
,跟image一样相对于父容器的一个比例,改为0.75
,Height
改为0.5
。然后你又会发现再拖一个label
进去跟之前拖进去一个image之后在拖label进去情况差不多一样,根本没在Group
里面显示出来,至于为什么在前面已经说了。这是因为在Apple Watch里面每个控件的Alignment...
有经验的同学就可能想到了用Group
在当作两个label
的父容器。对的,就是这么干。修改
Group
的Layout
为Vertical
,然后修改Width
为相对于父容器的0.75
,Height
为1
。再修改label
的Width
为相对于父容器的1
,Height为
想对于父容器的0.5
,另外一个label
参照第一个label来做。这样就完成了我们自定义cell
界面的布局。那么接下来就是该为我们的控件拉
IBOutlet
了,自定义一个class,继承至NSObject
,好奇的同学可能又会问了,为什么是NSObject
?,不应该是xxCell
么?在前面我也说过了在Apple Watch
根本没有什么View
,所有的控件
都是继承至NSObject
把
image
和两个label
拉个IBOutlet
到刚刚新建的classPaste_Image.png
在
.h
文件自定义一个methodPaste_Image.png
HiSchool
是我自定义的一个Model,具体内容如下
static NSString *const kWCAvarat = @"avatar";
static NSString *const kWCName = @"name";
static NSString *const kWCContent = @"content";
@interface HiSchool : NSObject
@property (nonatomic, strong) NSData *avatarData;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *content;
回到.m
文件实现- (void)setCellContent:(HiSchool *)content
- (void)setCellContent:(HiSchool *)content {
[self.avatarImage setImageData:content.avatarData];
[self.nikeNameLabel setText:content.name];
[self.contentLabel setText:content.content];
}
把table
拉个IBOutlet
到InterfaceController.m
,Apple Watch的table没有iOS端那么复杂,没有delegate
,dataSource
最后配置Apple Watch端的WCSession
会话,接收iOS App端发送过来的数据
#pragma mark - WCSessionDelegate
//* 接收数据方式1 配合 transferCurrentComplicationUserInfo */
- (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary<NSString *,id> *)userInfo {
[self setTableCell:userInfo];
}
//* 接收数据方式2 配合 sendMessage: replyHandler: errorHandler: */
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *,id> *)message {
[self setTableCell:message];
}
- (void)setTableCell:(NSDictionary *)dic {
WEAKSELF
dispatch_async(dispatch_get_main_queue(), ^{
HiSchool *hischool = [HiSchool new];
hischool.avatarData = dic[kWCAvarat];
hischool.name = dic[kWCName];
hischool.content = dic[kWCContent];
[weakSelf.allReceiveObjects addObject:hischool];
[weakSelf.headerBtn setTitle:[NSString stringWithFormat:@"count:%i\n点击此处删除全部",weakSelf.allReceiveObjects.count]];
//* 新增数据 */
[weakSelf.tableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:0] withRowType:@"HSCell"];
HiSchoolCell *cell = [weakSelf.tableView rowControllerAtIndex:0];
[cell setCellContent:hischool];
});
}
总结
1、iOS App与Apple Watch之间通信使用WCSession
会话类,WCSessionDelegate
协议的函数默认在子线程执行
2、Apple Watch上面的所有UI布局全部使用storyboard
3、Apple Watch里面所有的class不管是不是控件都是继承至NSObject
推荐一个不错的学习Apple watch开发的网站 watchKit相关编程问题
网友评论