ios自动化测试部分知识

最近在看关于iOS自动化测试的内容,其中比较常用的有KIF等,然后自己看他的实现时,发现有个beforeAll和AfterAll的方法,因为在当初写case的时候,不能知道所有case开始,和结束的时机,于是就对它比较好奇,看了他的实现。

socket连接池的实现探索

点评长连接的是建立一个TCP连接,然后发送一定策略的心跳检测,保持套接字(TCP+port)socket的连接不断开。

然后看到携程关于网络优化的[文章]

Native模块是携程的核心业务模块(酒店、机票、火车票、攻略等),Native模块的网络服务主要通过TCP连接实现,而非常见的Restful HTTP API那种HTTP连接,只有少数轻量级服务使用HTTP接口作为补充。

TCP连接网络服务模块使用了长连接+短连接机制,即有一个长连接池保持一定数目长连接,用于减少每次服务额外的连接,服务完成后会将该连接Socket放回长连接池,继续保持连接状态(一段时间空闲后会被回收);短连接作为补充,每次服务完成后便会主动关闭连接。

点评默认的是一个Socket连接,所有还比较简单,但是如果让实现一个连接池的话,应该怎么做到呢,这个池是如何表示的?

url encode的问题

URL参数encode的问题

外卖下单时,会先检测用户是否绑定了手机号,如果没有绑定,preview会提示进行绑定,跳转到绑定手机页面,如果绑定成功,就继续回到preview页面。

这就需要将preview的URLAction传递给绑定手机页面,它再进行一个透传。

iOS代码编译速度优化

cleaner源码编译速度优化方案

  1. 参考最新的cleaner,主要是清理头文件之间的依赖,尽量都采取直接依赖,而不是通过间接依赖,比A依赖B,B依赖C。而A如果依赖C的时候,最好是直接通过采用A依赖C的操作,而不是A->B->C的操作。

cleaner要求,在所有的.h文件中,基本都采用@class,@protocol的形式添加声明,然后在.m文件中添加#import的操作,这样是可以最小限度的减少依赖环节,但是也是有弊端的:

比如常用的model嵌套,如果采用@class的声明的方式,在vm或者v中使用model的时候,都要将他的子model的头文件也添加上,还是比较繁琐的。但是采用这样的操作,可以最大限度的降低头文件依赖和编译时间,所以平台也是在大力推广。

  1. 同时为了解决各个模块混乱依赖的问题,公司也要求将prefix.h文件给去掉,但是个人感觉还是可以添加一最常用的,比如 UIKit,NSFoundation等

  2. pch的,苹果在xcode6中已经不建议使用了,原因可能是,大家总是把一些头文件都放到prefix中,就导致各个头文件都会包含所有prefix中所包含的,每个文件依赖增多,编译时间也会增加。参考Code Smells in Objective-C

carthage初入

carthage是什么

Carthage
英 [ˈkɑ:θidʒ] 美 [ˈkɑrθɪdʒ]
n.
迦太基(非洲北部,今突尼斯的奴隶制城邦,腓尼基人所建,公元146年被罗马帝国所灭,见Punic Wars)
网络
迦太基古城; 迦太基遗址; 迦太基城

carthage是一个iOS的包依赖管理工具,相对于CocoaPods,他的目标是去中心化的依赖管理器。
它没有总项目的列表,这能够减少维护工作并且避免任何中心化带来的问题(如中央服务器宕机)。不过,这样也有一些缺点,就是项目的发现将更困难,用户将依赖于Github的趋势页面或者类似的代码库来寻找项目。

dispatch_after使用注意

注意

开发中,经常需要dispatch_after进行延迟处理,dispatch_after能让我们添加进队列的任务延时执行,该函数并不是在指定时间后执行处理,而只是在指定时间追加处理到dispatch_queue该方法的第一个参数是time,第二个参数是dispatch_queue,第三个参数是要执行的block。dispatch_time_t有两种形式的构造方式,第一种相对时间:DISPATCH_TIME_NOW表示现在,NSEC_PER_SEC表示的是秒数,它还提供了NSEC_PER_MSEC表示毫秒。
第二种是绝对时间,通过dispatch_walltime函数来获取,dispatch_walltime需要使用一个timespec的结构体来得到dispatch_time_t。

注意:不是一定在给定时间后执行相关的任务,而是在一定时间后,将执行的操作加入到队列中,然后队列里面再分配执行的时间,所以即使给了个 0秒 也不会立即执行,而是会追加一个Runloop的时间,一般是1/60s

测试代码如下

1
2
3
4
5
6
7
8
9
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"in after");
});
NSLog(@"viewDidLoad");
打印的顺序是这样:
2016-08-03 09:41:06.237 testDispatchAfter[29364:9056216] viewDidLoad
2016-08-03 09:41:06.244 testDispatchAfter[29364:9056216] in after

那有什么问题呢?

所以如果我们在使用dispatch_after的时候,比如有时候需要判断条件,特别是有些针对版本的判断,比如<= iOS7上,需要进行一定的延迟处理:
比如

1
2
3
4
5
6
7
8
NSString *string = @"测试";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSString *afterString = [@"name in after" stringByAppendingString:string];
NSLog(@"%@", afterString);
});
NSLog(@"%@", string);
string = nil;

虽然测试的过程中,没有crash。但是我们在代码逻辑里还是要避免这样的操作,因为是有可能,在dispatch_after的block执行之前,释放了某些变量,导致block出错的。