当前位置: 移动技术网 > 移动技术>移动开发>IOS > iOS面试题- AFN2.x为什么添加一条常驻线程?

iOS面试题- AFN2.x为什么添加一条常驻线程?

2018年09月30日  | 移动技术网移动技术  | 我要评论

1、afn2.x为什么添加一条常驻线程?

afn2.0里面把每一个网络请求的发起和解析都放在了一个线程里执行。正常来说,一个线程执行完任务后就退出了。开启runloop是为了防止线程退出。一方面避免每次请求都要创建新的线程;另一方面,因为connection的请求是异步的,如果不开启runloop,线程执行完代码后不会等待网络请求完的回调就退出了,这会导致网络回调的代理方法不执行。

这是一个单例,用nsthread创建了一个线程,并且为这个线程添加了一个runloop,并且加了一个nsmachport,来防止runloop直接退出。 这条线程就是af用来发起网络请求,并且接受网络请求回调的线程,仅仅就这一条线程

2、afn3.x为什么不再需要常驻线程?

nsurlconnection的一大痛点就是:发起请求后,这条线程并不能随风而去,而需要一直处于等待回调的状态。

苹果也是明白了这一痛点,从ios9.0开始 deprecated 了nsurlconnection。 替代方案就是nsurlsession。

self.operationqueue = [[nsoperationqueue alloc] init];
self.operationqueue.maxconcurrentoperationcount = 1;
self.session = [nsurlsession sessionwithconfiguration:self.sessionconfiguration delegate:self delegatequeue:self.operationqueue];

为什么说nsurlsession解决了nsurlconnection的痛点,从上面的代码可以看出,nsurlsession发起的请求,不再需要在当前线程进行代理方法的回调!可以指定回调的delegatequeue,这样我们就不用为了等待代理回调方法而苦苦保活线程了。

同时还要注意一下,指定的用于接收回调的queue的maxconcurrentoperationcount设为了1,这里目的是想要让并发的请求串行的进行回调。
参考:https://www.jianshu.com/p/b5c27669e2c1

3、为什么af3.0中需要设置self.operationqueue.maxconcurrentoperationcount = 1;而af2.0却不需要?

功能不一样:af3.0的operationqueue是用来接收nsurlsessiondelegate回调的,鉴于一些多线程数据访问的安全性考虑,设置了maxconcurrentoperationcount = 1来达到串行回调的效果。
而af2.0的operationqueue是用来添加operation并进行并发请求的,所以不要设置为1。

4、kvc原理

设值

当调用setvalue:属性值 forkey:@”name“的代码时,底层的执行机制如下:
* 程序优先调用set:属性值方法,代码通过setter方法完成设置。注意,这里的是指成员变量名,首字母大小写要符合kvc的命名规则,下同
* 如果没有找到setname:方法,kvc机制会检查+ (bool)accessinstancevariablesdirectly方法有没有返回yes,默认该方法会返回yes,如果你重写了该方法让其返回no的话,那么在这一步kvc会执行setvalue:forundefinedkey:方法,不过一般开发者不会这么做。所以kvc机制会搜索该类里面有没有名为的成员变量,无论该变量是在类接口处定义,还是在类实现处定义,也无论用了什么样的访问修饰符,只在存在以命名的变量,kvc都可以对该成员变量赋值。
* 如果该类即没有set:方法,也没有_成员变量,kvc机制会搜索_is的成员变量。
* 和上面一样,如果该类即没有set:方法,也没有_和_is成员变量,kvc机制再会继续搜索和is的成员变量。再给它们赋值。
* 如果上面列出的方法或者成员变量都不存在,将会执行该对象的setvalue:forundefinedkey:方法,默认是抛出异常。

取值

当调用valueforkey:@”name“的代码时,kvc对key的搜索方式不同于setvalue:属性值 forkey:@”name“,其搜索方式如下:
* 首先按get,,is的顺序方法查找getter方法,找到的话会直接调用。如果是bool或者int等值类型, 会将其包装成一个nsnumber对象。
* 如果上面的getter没有找到,kvc则会查找countof,objectinatindex或atindexes格式的方法。如果countof方法和另外两个方法中的一个被找到,那么就会返回一个可以响应nsarray所有方法的代理集合(它是nskeyvaluearray,是nsarray的子类),调用这个代理集合的方法,或者说给这个代理集合发送属于nsarray的方法,就会以countof,objectinatindex或atindexes这几个方法组合的形式调用。还有一个可选的get:range:方法。所以你想重新定义kvc的一些功能,你可以添加这些方法,需要注意的是你的方法名要符合kvc的标准命名方法,包括方法签名。
* 如果上面的方法没有找到,那么会同时查找countof,enumeratorof,memberof格式的方法。如果这三个方法都找到,那么就返回一个可以响应nsset所的方法的代理集合,和上面一样,给这个代理集合发nsset的消息,就会以countof,enumeratorof,memberof组合的形式调用。
* 如果还没有找到,再检查类方法+ (bool)accessinstancevariablesdirectly,如果返回yes(默认行为),那么和先前的设值一样,会按_,_is,,is的顺序搜索成员变量名,这里不推荐这么做,因为这样直接访问实例变量破坏了封装性,使代码更脆弱。如果重写了类方法+ (bool)accessinstancevariablesdirectly返回no的话,那么会直接调用valueforundefinedkey:
* 还没有找到的话,调用valueforundefinedkey:

5、苹果是如何实现autorelease pool的?

autoreleasepool 以一个队列数组的形式实现,主要通过下列三个函数完成.
* objc_autoreleasepoolpush
* objc_autoreleasepoolpop
* objc_autorelease
看函数名就可以知道,对 autorelease 分别执行 push,和 pop 操作。销毁对象时执行release操作。

6、数据结构与算法

例如:
* 字符串
* 链表
* 排序
* 栈和队列
* 堆
* 二叉树
* 哈希表
* 图

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网