Apple Watch和iOS App之间的通信&Apple Watch自定义Cell

先看看要实现的效果

2016-05-12 22.27.44.gif

第一步:打开Xcode 新建一个Apple Watch项目或者为已有项目添加Apple Watch支持

新建一个Apple Watch项目
Apple Watch和iOS App之间的通信&Apple Watch自定义Cell_第1张图片
新建一个Apple Watch项目.png
已有项目添加Apple Watch支持
Apple Watch和iOS App之间的通信&Apple Watch自定义Cell_第2张图片
为已有项目添加Apple Watch支持.png

第二步:如何实现Apple Watch和iOS app之间的通信

Apple Watch和iOS app之间的通讯使用WCSession类,在iOS App端
  1. 导入头文件
#import 
  1. 配置WCSession会话
 self.session = [WCSession defaultSession];
 self.session.delegate = self;
 //* 必须激活session */
 [self.session activateSession];

遵守WCSessionDelegate协议并实现session: didFinishUserInfoTransfer: error:方法,查看Apple Watch端和iOS端是否存在配对失败或者WCSession会话未激活等错误信息。

  1. iOS端发送消息给Apple Watch端(两种常用方法(1,2))
  2. 使用transferCurrentComplicationUserInfo这种只能传NSDictionary
  3. 使用sendMessage: replyHandler: errorHandler:或者sendMessageData: replyHandler: errorHandler:,前面一种也是只能传NSDictionary,后面一种看方法都知道要传的是一个NSData
  4. 使用transferFile: metadata:还能传文件可见WCSession真的很强大
  5. 接收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和iOS App之间的通信&Apple Watch自定义Cell_第3张图片
1111.png

在Apple Watch上面所有 class不管是不是控件都是继承至 NSObject,而且都是使用 set方法

进入正题:进入Interface.storyboard,找到Interface Controller Scene这个界面就是我们看到的第一个界面。

拖一个tableInterface Controller Scene里面,你会发现它会自动的跑到顶部,不管你放到哪个位置。这个问题等会儿下面会讲。细心的人可能还会发现table下面是一个Row Controller而不是和iOS App那样是一个Cell

Apple Watch table.png

Apple Watch和iOS App之间的通信&Apple Watch自定义Cell_第4张图片
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默认是LeftVertical默认是Top,这也是为什么刚开始就说拖一个控件到Interface Controller Scene里面,不管在什么位置都会自己跑到顶部的原因。
既然知道是什么原因了,那就改吧。点击image,在右侧第4个检查器改Size

size.png

第一个是说根据内容大小调整宽高
第二个是说相对于父容器来说的一个比例
第三个是说给定一个固定的宽高
我使用的是第二个,相对于父容器的一个比例 Width0.25Height0.8,然后修改 Verticalcenter
再继续,label,拖进去之后修改label的 Width,跟image一样相对于父容器的一个比例,改为 0.75Height改为 0.5。然后你又会发现再拖一个 label进去跟之前拖进去一个image之后在拖label进去情况差不多一样,根本没在 Group里面显示出来,至于为什么在前面已经说了。 这是因为在Apple Watch里面每个控件的Alignment...有经验的同学就可能想到了用 Group在当作两个 label的父容器。对的,就是这么干。
修改 GroupLayoutVertical,然后修改 Width为相对于父容器的 0.75Height1。再修改 labelWidth为相对于父容器的 1Height为想对于父容器的 0.5,另外一个 label参照第一个label来做。这样就完成了我们自定义 cell界面的布局。
那么接下来就是该为我们的控件拉 IBOutlet了,自定义一个class,继承至 NSObject,好奇的同学可能又会问了,为什么是 NSObject?,不应该是 xxCell么?在前面我也说过了在 Apple Watch根本没有什么 View,所有的 控件都是继承至 NSObject
image和两个 label拉个 IBOutlet到刚刚新建的class
Apple Watch和iOS App之间的通信&Apple Watch自定义Cell_第5张图片
Paste_Image.png

.h文件自定义一个method
Apple Watch和iOS App之间的通信&Apple Watch自定义Cell_第6张图片
Paste_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拉个IBOutletInterfaceController.m,Apple Watch的table没有iOS端那么复杂,没有delegatedataSource

最后配置Apple Watch端的WCSession会话,接收iOS App端发送过来的数据

#pragma mark - WCSessionDelegate
//* 接收数据方式1 配合 transferCurrentComplicationUserInfo */
- (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary *)userInfo {
    [self setTableCell:userInfo];
}
//* 接收数据方式2 配合 sendMessage: replyHandler: errorHandler: */
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary *)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相关编程问题

Demo

你可能感兴趣的:(Apple Watch和iOS App之间的通信&Apple Watch自定义Cell)