美文网首页
iOS | iWatch开发 没有转圈的数据请求 是没有灵魂的

iOS | iWatch开发 没有转圈的数据请求 是没有灵魂的

作者: BinaryBang | 来源:发表于2020-03-07 18:11 被阅读0次

表弟最近在开发一个独立的iWatch手表应用,需要应用独立地调用接口去请求数据,而不是和iPhone通信来交换数据.
调接口请求数据本身没什么问题,NSURLSessionDataTask类不仅适用于iPhone,iWatch也能使用.所以AFNetworking等常规请求库,是可以直接使用的.

但是,有一个问题比较尴尬.
平时我们在网络请求时,都会转个圈,提示用户,我正在请求数据.

虽然很多用户神烦这个转圈,但是转圈真的很重要:

  • 防止用户重复操作. 有的关键的操作,比如提交订单时,防止用户重复提交.
  • 告诉用户系统没有死机. 有的时候,请求数据比较长,通过转圈告诉用户,系统本统依然健在,请耐心等待.
  • 提升吸引力.有的应用把转圈的功能也做得很友好,甚至通过转圈就能提升用户的好感.

iPhone上还有专门的UIActivityIndicatorView来处理这个事情.
但是WatckKit中,没有哇...
表弟有点想让请求中按钮变灰的方式来对应.

作为一个优雅的程序员,不允许这样的事情发生.
所以,这一次我们来让菊花(转圈)在Watch应用中绽放!

1 Demo说明

本文的目标,是创建一个实现以下的基本功能的应用:
点击按钮->请求接口->转圈->收到数据->转圈消失,解析数据,显示Table.
基本的流程如下图:



最终效果:



这个gif目前只能播放一遍,需要刷新以下才能观看,原因还在调查中.

2 WatchApp如何显示动态图片

WatchKit中,播放图片的组件是WKInterfaceImage,详细信息可以参考这篇官方文档译文:WKInterfaceImage-官方文档译文

gif文件实际上是一系列图片的组合,不能和jpg或者png那样,直接播放,需要进行额外的处理.这里介绍两种方式播放gif文件:

2.1 把gif资源放在WatchKitApp资源目录

  • 2.1.1 获取gif的每一帧资源
  • 2.1.2 在WatchKitApp的资源目录中,新建loading文件夹,然后文件名按照loading0,loading1...这样的方式命名:


  • 2.1.3 使用以下代码,显示动态图像
```
[interfaceImage setImageNamed:@"loading"];
[interfaceImage startAnimating];
```

2.2 程序自动提取gif的每一帧

  • 2.2.1 将图片放到WatchKit Extension bundle中,确保你的图片的Target Membership情况为:


  • 2.2.2 用以下代码,提取gif的每一帧图片,并返回一个动画图片序列的UIImage对象
/*
name:要播放的gif图片名;
duration:在多少时间内放完;
*/
- (UIImage *)gifImageNamed:(NSString *)name duration:(NSInteger)duration {
   //获取资源文件的路径
   NSString * path = [[NSBundle mainBundle] pathForResource:name ofType:nil];
   if(!path){
       NSLog(@"文件不存在!");
       return nil;
   }
   //加载NSData图片数据
   NSData * data = [NSData dataWithContentsOfFile:path];
   CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
   size_t count = CGImageSourceGetCount(source);
   if (count <= 1) {
       return [[UIImage alloc] initWithData:data];
   }
   NSMutableArray *images = [NSMutableArray array];
   
   for (size_t i = 0; i < count; i++) {
       //在栈中创建一个图片数据结构
       CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, i, NULL);
       if (!imageRef) {
           continue;
       }
       //根据图片数据结构,创建一个UIImage对象
       [images addObject:[UIImage imageWithCGImage:imageRef]];
       
       //释放已经生成了UIImage对象的图片数据结构
       CGImageRelease(imageRef);
   }
   
   UIImage *animatedImage = [UIImage animatedImageWithImages:images duration:duration];
   
   CFRelease(source);
   
   return animatedImage;
}
  • 2.2.3 使用以下代码显示该动画图片:
[self.ifImage setImage:[self gifImageNamed:@"wait.gif" duration:2]];
[self.ifImage startAnimating];

3 WKInterfaceTable的使用

WatchKit中的表视图是WKInterfaceTable类,相比于UITableView,使用上简化了很多.

3.1 Cell的配置

WKInterfaceTable将负责Cell显示的类,叫做TableRowController,我们需要自定义一个类来承担TableRowController这样的角色.
TableRowController被关联了一个Group,用来对cell上面要呈现的空间进行布局.我们可以将这些控件关联到TableRowController对应的类上,进行控制.

  • 3.1.1 在故事板中,拖入一个WKInterfaceTable类.

  • 3.1.2 新建一个类TableCell,继承NSObject.需要导入WatchKit:

#import <WatchKit/WatchKit.h>
  • 3.1.3 在故事板中的界面上选中Table里的TableRowController,选中id检测器,为其指定类为我们新建的TableCell:


  • 3.1.4 在属性检测器中,指定id为"TableCell",在之后的程序中会用到.


  • 3.1.5 选中TableRowController下面的Group,并添加一个WKInterfaceLabel.

  • 3.1.6 选中WKInterfaceLabel,并关联到TableCell.h文件的输出口中:

@interface TableCell : NSObject
@property (weak, nonatomic) IBOutlet WKInterfaceLabel *ifLabel;
@end

这样,cell就配置好了.

3.2 Table的配置

cell配置完毕之后,就是配置Table了.

  • 3.2.1 配置Table的Cell数量
    UITableView是通过代理方法获取Cell的数量的,WKInterfaceTable,则是直接设置需要的Cell数量:
    //假如要显示4个Cell
    [table setNumberOfRows:4 withRowType:@"TableCell"];

注意,这里要指定RowController的Type,需要和3.1.4中设置的保持一致.

  • 3.2.2 设置每个Cell的标题
    UITableView也是通过代理方法设置cell的显示内容.
    WKInterfaceTable,是直接遍历每个RowController进行控制:
    //arr是标题的字符串数组.
    for(int i = 0; i < table.numberOfRows;i++) {
        TableCell * cell = [table rowControllerAtIndex:i];
        NSString * title = arr[I];
        [cell.ifLabel setText:title];
    }
  • 3.2.3 设置点击事件
    WKInterfaceTable的点击事件,会直接传给InterfaceController的该方法,而不需要设置代理.
- (void)table:(WKInterfaceTable *)table didSelectRowAtIndex:(NSInteger)rowIndex {
     NSString * title = self.arr[rowIndex];
    NSLog(@"Click %@",title);
}

这样,table也设置好了.

4 WKInterfaceGroup的使用

在显示转圈的时候还有一个问题.

我们在转圈的时候,转圈的图片和Table的位置其实是在一个位置的,在没有数据时,显示转圈图片,隐藏Table;在有数据时,显示Table,隐藏转圈图片.

但是在WatchKit的InterfaceController中,一般只能竖直向下排列,不能两个控件占用同一个位置.只有InterfaceGroup提供了内容元素的布局功能;

InterfaceGroup的内容包含3中布局方式,Horizontal,Vertical,Overlap.

  • Horizontal,则里面的内容都是水平方向排列
  • Vertical,内容都是竖直方向排列
  • Overlap,内容都是互相覆盖的.
    所以Overlap符合我们的要求.

但是,我们希望在Table的下方有个返回的按钮,这就不能让Table和返回按钮一起在这个Overlap的Group里,否则他们会互相重叠.

所以,最终的方案是:

  • 让Table和返回按钮在一个Vertical布局的Group里;
  • 让VerticalGroup,转圈的图片,请求的按钮在一个Overlap布局的Group里

最后还有一点需要注意,在数据返回之后,Table的高度发生了变化需要让Overlap的Group重新调整一下高度,否则不能滚动:

[self.ifGroupRoot sizeToFitHeight];

5 真机请求时的一个大坑

在模拟器调式的时候,很顺利,得到了预期的效果.
但是在真机调式的时候,总是提示"The Internet connection appears to be offline".

这个问题让我头疼了好久.

最终发现可能的原因:

  • i 我的WatchApp是通过和iPhone配对安装上去的,所以iWatch和iPhone保持着配对关系.
  • ii iWatch配对的iPhone在线时,iWatch并不会自己去请求数据,而是通过iPhone去请求数据
  • iii 但是我这个应用是独立的iWatch应用,并没有和iPhone有数据交互,所以提示网络不同.

最终解决的办法是: 让配对的手机关机,飞行模式,或者接触配对.

6 总结

iWatch开发目前相关资料不是那么充足,一路上遇到了很多问题.希望记录下这些问题作为总结,并帮助有需要的人.

项目源代码放到百度网盘上了:
链接:https://pan.baidu.com/s/1jq2lTw3zU-nTsgN2EHQjrw
密码:fdih
运行环境:Xcode 11.3.1
模拟器应该可以直接运行,跑真机的话要注意本文的第5点.

如果这篇文章帮到了你,请点赞,关注,鼓励一下哈~~~

参考资料

1.WKInterfaceImage-官方文档译文

相关文章

  • iOS | iWatch开发 没有转圈的数据请求 是没有灵魂的

    表弟最近在开发一个独立的iWatch手表应用,需要应用独立地调用接口去请求数据,而不是和iPhone通信来交换数据...

  • OC 网络请求中文转URL编码

    在iOS的开发中,有时候一个网络请求用英文请求没问题,用中文请求的时候,就没有数据了,然而安卓又是OK的!有些人就...

  • GCD和网络加载的一点整理(二)

    iOS开发中经常会碰到发起一个网络请求,还要在开始的时候写加载菊花转圈的代码,在网络请求示完成之后还要隐藏掉菊花转...

  • 2018-05-17

    ios网络请求,之前从来没有接触过iOS,最近要做一个app,做到网络请求这(就是通过URL来请求数据),自己总结...

  • iOS 文件操作简介

    在iOS开发过程中,网络出错没有返回正确数据时有发生,这时可以读取本地数据展示给用户来优化用户体验,并且在网络请求...

  • iOS开发YN组件之网络层

    iOS开发组件YNKit之网络数据请求 该组件由我和占宇同事共同开发的iOS开发高效的一个组件集,在快捷开发中提炼...

  • 字典转模型

    2016.08.31更新 ios开发中网络请求,通常返回json数据,如果想使用数据就必须把json格式的数据转成...

  • iOS开发·网络请求方法总结复习(下)

    iOS开发·网络请求方法总结复习(下) iOS开发·网络请求方法总结复习(下)

  • iOS做了四年业务代码,还想继续码UI吗?

    今年是做iOS开发第四个年头,大部分时间是从事界面,数据请求、解析,写了一大堆的业务代码,技术却没有很大的提高。虽...

  • 网络数据请求自身心得

    今天来说说关于iOS开发过程中的网络数据请求。 现在常用的网络数据请求常见的有四种方式:同步GET,同步POST,...

网友评论

      本文标题:iOS | iWatch开发 没有转圈的数据请求 是没有灵魂的

      本文链接:https://www.haomeiwen.com/subject/rbccdhtx.html