最近忙了一阵子Apple Watch 的开发。虽然Apple Watch 4马上就要发布了,但详细的中文开发资料还不是很多。我这里就不按照步骤走了,总结一下非常规的知识点以及个人理解。


  • 静态布局

    所有静态UI控件都在 Storyboard 上完成,彻底抛弃frame的概念。WatchKit 布局方式很像CSS,包括绝对布局和相对布局,支持横向排列和纵向排列,UI之间无法重叠。但可以使用 Group 处理。 比如我们去拖一个 左图片 右文字 的 Button,该如何操作呢?

    1、拖一个button, 设置其 Content 为 Group 类型(默认为 Text)。

    2、在该 Group 上再拖一个 Group2 ,用来容纳图片和文字,只要让该 Group2 居中,那么图片和文字就可以居中啦。

    3、设置 Group2 的 Layout 为 Horizontal ,在 Group2 上拖进来一个 WKInterfaceImage 和一个 WKInterfaceLabel 即可。

    具体层级关系如下图:


  • 动态绘制

    WatchKit 上的 UI 控件不多,和 UIKit 有些类似。但由于不支持frame的概念,所以很难处理根据网络数据的不同,frame 不同的问题。比如这种曲线图。

    WatchKit 上没有提供 CALayer 相关的 类。但可以采用 UIBezierPath 和 CGContextRef 相结合的方法去动态绘制。绘制完成后,将画布合成为 UIImage, 然后就可以放到 WKInterfaceImage 上显示了。

    需要注意的是,画布的大小要设置为屏幕尺寸的二倍(或者直接乘以 screenScale ),不然绘制出来的很模糊。

    这里只摘要一小段代码示例(根据不同体重绘制不同位置的白点)

    - (void)drawGraph{CGFloat graphWidth = CGRectGetWidth([WKInterfaceDevice currentDevice].screenBounds);CGFloat graphHeight = CGRectGetWidth([WKInterfaceDevice currentDevice].screenBounds);float scaleFactor = [WKInterfaceDevice currentDevice].screenScale;CGSize size = CGSizeMake(graphWidth*scaleFactor, graphHeight*scaleFactor);NSArray *positionsArray = [self transPointToValue:self.dataArray];UIGraphicsBeginImageContext(size);CGContextRef context = UIGraphicsGetCurrentContext();//绘制体重的小白点[self drawWhiteDotPath:positionsArray];/*这里你可以绘制任何东西*/UIImage *image = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];UIGraphicsEndImageContext();[self.weightCurveImage setImage:image];
    }
    - (void)drawWhiteDotPath:(NSArray *)pointArray{for (NSValue *pointValue in pointArray) {UIBezierPath *dotPath = [UIBezierPath bezierPath];[[UIColor whiteColor] setStroke];[[UIColor whiteColor] setFill];[dotPath addArcWithCenter:pointValue.CGPointValue radius:5 startAngle:0 endAngle:2*M_PI clockwise:YES];dotPath.lineWidth = 1;[dotPath fill];[dotPath stroke];}
    }

  • 数据交互(未激活虚拟SIM卡的情况,激活之后是否一样还待测试)

    首先知道一点,在 watchOS 2.0之前,只能通过蓝牙进行数据传输。Watch上的网络请求也是交给 iPhone 去发起,然后把结果传递回来。而之后,Apple Watch 支持连接WIFI,利用 NSURLSession 可以自主发起网络请求。

    1、与手机处于同一 WiFi 下,手机会把该 WiFi 共享给 Watch。

    2、iPhone 和 Watch 正常连接,如果 iPhone 断开网络,Watch 也无法使用自己的WiFi。

    3、iPhone 和 Watch 断开连接(iPhone关闭蓝牙),等半分钟左右,Watch 会使用自主的WiFi。

    WCSession

    正常连接的时候可以通过 WCSession 进行网络通信。 Watch 通过 WCSession 给 iPhone上的app 发送消息,会静默启动app。但反过来却不会。

    sendMessage 为异步操作,所以涉及到更新UI的情况,注意要在主线程中进行。

    [session sendMessage:@{@"xxx":@"xxx"} replyHandler:^(NSDictionary<NSString *,id> * _Nonnull replyMessage) {
    NSDictionary *messageDict = (NSDictionary *)replyMessage;
    dispatch_async(dispatch_get_main_queue(), ^{//更新UI
    });
    } errorHandler:^(NSError * _Nonnull error) {}];

    官方文档说 session 的激活再要尽量早的地方,一般在 app 的 didFinishLaunchingWithOptions进行激活,可以为此专门建一个类,作为 session 的 delegate ,这样可以避免在 AppDelegate 写太多代码,保持简洁。而 Watch 方面 Session 的激活,可以在 InterfaceController 类的awakeWithContext方法里进行。

    另外,为了保持Session的稳定性,要在断开连接的时候做一下激活Session的处理。

    iPhone方面:

    - (void)sessionDidDeactivate:(WCSession *)session __IOS_AVAILABLE(9.3) __WATCHOS_UNAVAILABLE{//重新启动 Sessionif ([WCSession isSupported]) {WCSession *session = [WCSession defaultSession];session.delegate = self;[session activateSession];}
    }

    Apple Watch 方面:

    - (void)sessionReachabilityDidChange:(WCSession *)session{
    //重新启动 Sessionif (!session.reachable) {WCSession *session = [WCSession defaultSession];session.delegate = self;[session activateSession];}
    }

    NSURLSession

    如上文提到的,当 Watch 与iPhone 断开连接,可以自主发起网络请求:

      NSString *urlString = [your.host stringByAppendingString:urlString];NSMutableDictionary *headers = [NSMutableDictionary dictionary];[headers setValue:@"application/json; charset=utf-8" forKey:@"Content-Type"];[headers setValue:@"application/json" forKey:@"Accept"];NSURL *url = [NSURL URLWithString:urlString];NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];[request setHTTPMethod:your.methordType?:@"GET"];//设置 headerfor (NSString *keyString in headers.allKeys) {[request addValue:headers[keyString] forHTTPHeaderField:keyString];}//设置请求参数NSMutableDictionary *tempDcit = [[NSMutableDictionary alloc] initWithDictionary:parameters];[tempDcit setValue:@"xxxx" forKey:@"xxxx"];[request setHTTPBody:[[tempDcit dictionaryToJsonString] dataUsingEncoding:NSUTF8StringEncoding]];NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];if (@available(watchOS 4.0, *)) {configuration.waitsForConnectivity = YES;}NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:requestcompletionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {//请求结果处理}];[dataTask resume];

    既然 Apple Watch 也有了网络请求,那么在开发过程中如何选择,是利用 NSURLSession自主请求还是利用 WCSession 把请求任务给手机,让手机传递请求结果呢?个人觉得最好的方案是两个都要兼容。建议对请求做一层封装过滤,如果 session.reachable 为YES,把请求交给 iPhone,否则,就由 Watch 发起请求。


  • Some Tips

    WKCrownDelegate

    通过准守 WKCrownDelegate 协议,我们可以监听表冠的旋转,实现自己的需求,比如调整数字。

    参考资料:传送门

    - (void)willActivate {[super willActivate];self.crownSequencer.delegate = self;[self.crownSequencer focus];
    }
    
    #pragma mark - WKCrownDelegateCGFloat crownAccumulator = 0.0;
    - (void)crownDidRotate:(nullable WKCrownSequencer *)crownSequencer rotationalDelta:(double)rotationalDelta API_AVAILABLE(watchos(3.0)){crownAccumulator += rotationalDelta;if (crownAccumulator > 0.1) {//让你的数字+0.1crownAccumulator = 0.0;} else if (crownAccumulator < -0.1) {//让你的数字-0.1crownAccumulator = 0.0;}
    }

    PS:通过改变参考值 0.1 来调整表冠的灵敏度。

​ 打包:

​ 对于iOS,bitcode是可选的;对于watchOS,bitcode是必须的;因此,Archive 的时候要把 WatchExtension 的 bitcode 设置为 YES; 版本号和构建号要和 app 保持一致。

=======完结

AppleWatch 开发的一些知识总结相关推荐

  1. AppleWatch开发教程之调试程序使用帮助文档

    AppleWatch开发教程之调试程序使用帮助文档 AppleWatch开发教程之调试程序 调试又被称为排错,是发现和减少程序错误的一个过程.在Xcode中进行调试的需要实现以下几个步骤: 1.添加断 ...

  2. AppleWatch开发教程之Watch应用对象新增内容介绍以及编写运行代码

    AppleWatch开发教程之Watch应用对象新增内容介绍以及编写运行代码 添加Watch应用对象时新增内容介绍 Watch应用对象添加到创建的项目中后,会包含两个部分:Watch App 和 Wa ...

  3. Android开发必看知识,不看后悔

    Android开发必看知识,不看后悔 打包为大家奉上最实用最给力的资源,不看你绝对后悔. 最强大的UI特效 奇艺高清UI界面源代码 http://www.eoeandroid.com/thread-1 ...

  4. 前端开发的浏览器知识

    前端开发的浏览器知识 1.1 在浏览器中输入url 用户输入url,例如http://www.feng.com.其中http为协议,www.feng.com为网络地址,及指出需要的资源在哪台计算机上. ...

  5. java webstock 在线直播_在线教育直播开发的这些知识你知道吗?

    线下教育在当代已经趋于落后了,随之而来的是大批的在线教育直播系统,许多大的互联网公司也想来分一杯羹,毕竟在线教育与线下教育相比,优势还是比较明显的,那么在线教育直播开发的相关知识您都知道多少呢? 1. ...

  6. OpenFOAM程序开发的基本知识(基本术语)

    OpenFOAM程序开发的基本知识(基本术语) OpenFOAM程序开发的基本知识 openFOAM的基本术语 重要的环境变量: $WM_PROJECT_USER_DIR ―― OpenFOAM的用户 ...

  7. 尝试:Script Lab,开发模式之知识储备//SL02

    前期00:深度:从 Office 365 新图标来看微软背后的设计新理念 前期01:尝试:Script Lab,快速 Office 365 开发工具 //SL01 本期02:尝试:Script Lab ...

  8. 前端开发之基础知识-HTML(一)

    1.1 html概述和基本结构 html概述 HTML是 HyperText Mark-up Language 的首字母简写,意思是超文本标记语言,超文本指的是超链接,标记指的是标签,是一种用来制作网 ...

  9. Android camera(4)---Android Camera开发之基础知识篇

    Android Camera开发之基础知识篇 转自:https://blog.csdn.net/feiduclear_up/article/details/51968975#jump5 概述 Andr ...

最新文章

  1. C# 调用WinRar解压压缩包
  2. python计算直角三角形顶点坐标
  3. 居民信息管理系统java_基于jsp的社区住户信息管理系统-JavaEE实现社区住户信息管理系统 - java项目源码...
  4. 一个小型的网页抓取系统的架构设计
  5. spring aop使用
  6. 前端面试题和setTimeout异步
  7. oracle分同步事务和异步事务,oracle的事务隔离
  8. matlab mysvd代码解释,关于使用SVD进行PCA主成分提取的代码问题!也是必须涉及到原理的!...
  9. Python并发机制的实现(一)——多进程
  10. linux 查看文件开头几行、末尾几行、中间几行
  11. Dubbo 服务 IP 注册错误踩坑经历
  12. spring异常+自定义以及使用
  13. jquery实现新浪微博的表情插件
  14. UltraEdit v17.00.0注册机
  15. 解决cmd中tomcat中文乱码问题
  16. 稳压二极管的原理和伏安特性
  17. 计算机管理里面和打印机相关的,打印机设备
  18. 2021技术人的百宝黑皮书
  19. 无线充电动牙刷PCBA单片机方案牙刷无线充底座IC芯片
  20. linux 脚本 expected,使用expect实现shell中scp自动输入密码

热门文章

  1. 将html转换为word文档的几种方式
  2. 根据经纬度计算指定范围内或者附近的人(java)
  3. xctf攻防世界 MISC高手进阶区 saleae
  4. 打开计算机网络自动连接,电脑网络怎么自动连接
  5. 【苹果家庭推送iMessage】软件安装应用程序访问HealthKit HomeKit
  6. 多功能网络侦查OSINT工具,FinalRecon
  7. IE和Outlook Express的翻译插件设计
  8. html img素材,html使用img标签和背景图片之间的区别
  9. 9月20日.周日 第一场正式的比赛:2020年CCPC网络赛
  10. ITS Mobile Template interpretation failed. Template does not exist