一、选择题
-
对以下四种多线程的技术简介错误的是( C )
A. pthread是一套通用的多线程API,适用于Unix\Linux\Windows等系统,跨平台\可移植,使用难度大
B. NSThread 是使用更加面向对象,简单易用,可直接操作线程对象
C. GCD是基于NSThread的,充分利用设备的多核
D. NSOperation基于GCD(底层是GCD)比GCD多了一些更简单实用的功能,使用更加面向对象 -
下面关于GCD说法不正确的是 ( C )
A. GCD是 C语言的“并发技术”框架
B. GCD是苹果公司为多核的并行运算提出的解决方案
C. GCD是直接对线程操作的并发编程.
D. GCD自动管理线程的生命周期(创建线程、调度任务、销毁线程等)
解析:
- GCD是苹果公司为多核的并行运算提出的解决方案
- GCD会自动利用更多的CPU内核(比如双核、四核)
- GCD对自动管理线程的生命周期(创建线程、调度任务、销毁线程)
- 程序员只需要告诉GCD想要执行什么任务、不需要编写线程任何管理代码
- 图片2.png
- GCD的队列可以分为( B )大类型 和( C )种队列
A. 1 B. 2 C. 3 D. 4
解析:
图片3-1.png
三种队列:
图片3-2.png
-
多选题,以下对Block的描述正确的是(ABC )
A. Block是一种数据类型,可以被当做参数传递
B. Block是一个能工作的代码单元,可以在任何需要的时候被执行
C. 默认情况下,不允许在块代码内部修改外部变量的数值
D. 用Block传值时要注意循环引用,当Block内引用局部变量时要用__weak修饰此变量来解除循环引用 -
对于语句NSString *str = [NSData alloc] init];在编译时和运行时分别是什么类型( D )
A. 编译时NSData,运行时NSData
B. 编译时NSString,运行时NSString
C. 编译时NSData,运行时NSString
D. 编译时NSString,运行时NSData -
数组中可以添加以下那种空值( B )
A. Nil 是类的空指针类型
B. NSNull 集合中的空值
C. nil 是对象的空指针类型
D. NULL 是其它类型(基本数据类型,C类型指针) 为空值
解析:
图片6.png
-
以下哪项不是创建线程的目的( D )
A.开启一条新的执行路径
B.运行指定的代码
C.把耗时操作放在后台执行
D.线程开的越多执行效率越快 -
关于NSURLSession说法错误的是( D )
A.NSURLSession是iOS7中新的网络接口,与NSURLConnection是并列的
B.当程序在前台时,NSURLSession与NSURLConnection大部分可以互相替代
C.NSURLSession支持后台网络操作,除非用户强行关闭
D.所有的NSURLSession对象必须共用一个NSURLSessionConfiguration
解析:
每一个NSURLSession对象都可以设置不同的NSURLSessionConfiguration,从而满足应用内不同类型的网络请求
- 以下哪项不属于耗时操作( D )
A. 从服务器请求用户信息
B. 文件上传/下载
C. 执行1万次NSLog(@“itcast");
D. 在本地判断用户名是否包含非法字符
解析:
- D选项.一般使用正则表达式判断用户名是否包含非法字符,不属于耗时操作.
- A.B.两项都与网络有关,都属于耗时操作
- C选项.NSLog性能比较低,打印1万次也是耗时操作,因此实际开发中在应用程序发布前都会将NSLog调试去掉.
- POST对上传的文件大小限制一般为( C )
A. 512KB B. 1M C. 2M D.无限
解析:
图片10.png
11.下面不属于block的定义的是( D )
A.返回类型 (^blockName)(参数列表) = ^返回类型 (参数列表) { /// 代码实现; }
B.void (^blockName)(参数列表) = ^ (参数列表) { /// 代码实现; }
C.void (^blockName) = ^ { /// 代码实现; }
D.void (^blockName)() = ^ { /// 代码实现; }
12.下面哪一个不是创建线程的方法( A )
A. [NSThread currentThread];
B.[selfperformSelectorInBackground:@selector(longOperation) withObject:nil];
C.[NSThread detachNewThreadSelector:@selector(longOperation) toTarget:selfwithObject:nil];
D.[[NSThread alloc] initWithTarget:selfselector:@selector(longOperation) object:nil]
13.对于单例理解正确的是( C )
A.单例是系统自带的类才有的。
B.单例系统运行时就创建了,不用自己创建。
C.单例是无论以何种方式来创建该类的对象,创建的对象总是同一个。
D.单例是系统给我们提供好的的一种高效率的创建对象的方法。
二、简答题
- KVO的实现原理,使用场景
- KVO的实现原理:
当某个类的对象第一次被观察时,系统就会在运行时动态地创建该类的一个派生类,在这个派生类中重写原类中被观察属性的setter方法,派生类在被重写的setter方法实现真正的通知机制(Person->NSKVONotifying_Person).
派生类重写了 class 方法以“欺骗”外部调用者它就是起初的那个类。然后系统将这个对象的isa指针指向这个新诞生的派生类,因此这个对象就成为该派生类的对象了,因而在该对象上对setter的调用就会调用重写的setter,从而激活键值通知机制。此外,派生类还重写了dealloc方法来释放资源。 - KVO使用场景:
1.实现上下拉刷新控件 contentoffset
2.webview混合排版 contentsize
3.监听模型属性实时更新UI
-
手写单例的实现
-
为什么弱引用一些类方法返回的对象没有释放(如 + (id)buttonWithType:(UIButtonType)buttonType;)? ARC中需要使用autorelease吗,为什么?自动释放池是如何工作的
很多类方法为了在代码块结束时引用的对象不会因无强引用而被释放内存采用自动释放的方式,当其最近的自动释放池释放时该对象才会释放.
ARC中手动添加autoreleasepool可用于提前释放使用自动释放策略的对象,防止大量自动释放的对象堆积造成内存峰值过高.
自动释放池时栈结构,每个线程的runloop运行时都会自动创建自动释放池,程序员可以代码手动创建自动释放池,自动释放的对象会被添加到最近的(栈顶)自动释放池中,系统自动创建的自动释放池在每个运行循环结束时销毁释放池并给池中所有对象发release消息,手动创建释放池在所在代码块结束时销毁释放池并发消息统一release -
NSOperationQueue和GCD的区别和类似的地方
1> GCD是纯C语言的API,NSOperationQueue是基于GCD的OC版本封装
2> GCD仅仅支持FIFO队列,只可以设置队列的优先级,而NSOperationQueue中的每一个任务都可以被重新设置优先级(setQueuePriority:),从而实现不同操作的执行顺序调整,
3> GCD不支持异步操作之间的依赖关系设置。如果某个操作的依赖另一个操作的数据,使用NSOperationQueue能够设置依赖按照正确的顺序执行操作(addDependency:)。GCD则没有内建的依赖关系支持(只能通过Barrior和同步任务手动实现)。
4> NSOperationQueue方便停止队列中的任务(cancelAllOperations, suspended),GCD不方便停止队列中的任务.
5> NSOperationQueue支持KVO,可以监测operation是否正在执行(isExecuted)、是否结束(isFinished),是否取消(isCanceld)
6> GCD的执行速度比NSOperationQueue快
7>NSOperationQueue可设置最大并发数量(节电),GCD具有dispatch_once(只执行一次,单例)和dispatch_after(延迟执行)功能 -
出现资源抢夺有哪些解决办法?
1> 互斥锁 @synchronized(xx) {...}
2> NSCondition NSLock
3> dispatch_barrior_async
4> dispatch_semaphore_wait -
请写出HTTP请求常用的几种方式。
GET :获取指定资源
POST :2M 向指定资源提交数据进行处理请求,在RESTful 风格用于新增资源
HEAD :获取指定资源头部信息
PUT :替换指定资源(不支持浏览器操作)
DELETE: 删除指定资源 -
如何使一个方法返回多个数据(这些数据不在一个集合或者自定义对象中)
传参指针变量的地址,方法内部通过*运算符使用该地址可以修改该地址保存的内容(引用对象的地址),当外部再次使用该指针变量取出引用对象时,引用对象已经在方法内部发生了改变,指针变量指向其他数据,相当于方法的返回值(经方法处理后生成的外部可使用的结果数据). -
(拓展)KVC可以修改只读属性吗,为什么? KVC的查找顺序是什么
KVC在某种程度上提供了访问器的替代方案。不过访问器方法是一个很好的东西,以至于只要是有可能,KVC也尽量再访问器方法的帮助下工作。为了设置或者返回对象属性,KVC按顺序使用如下技术:
①检查是否存在-<key>、-is<key>(只针对布尔值有效)或者-get<key>的访问器方法,如果有可能,就是用这些方法返回值;
检查是否存在名为-set<key>:的方法,并使用它做设置值。对于 -get<key>和 -set<key>:方法,将大写Key字符串的第一个字母,并与Cocoa的方法命名保持一致;
②如果上述方法不可用,则检查名为-_<key>、-_is<key>(只针对布尔值有效)、-_get<key>和-set<key>:方法;
③如果没有找到访问器方法,可以尝试直接访问实例变量。实例变量可以是名为:<key>或<key>;
④如果仍为找到,则调用valueForUndefinedKey:和setValue:forUndefinedKey:方法。这些方法的默认实现都是抛出异常,我们可以根据需要重写它们。 -
(拓展)TCP如何解决乱序和丢包问题,描述一下三次握手
图片 1.png
TCP数据包的头格式中有两个概念,Sequence Number是数据包的序号,用来解决网络包乱序(reordering)问题。Acknowledgement Number就是ACK——用于确认收到,用来解决不丢包的问题。
位码即tcp标志位,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)Sequence number(顺序号码) Acknowledge number(确认号码).
SeqNum的增加是和传输的字节数相关的,TCP传输数据时,如A主机第一次传输1440个字节,seq=1,那么第二次时seq = 1441,B拼接数据就是根据seq进行拼接的,seq数字不断累加避免了乱序.B主机收到第一次数据包以后会返回ack = 1441.
A主机收到B的ack = 1441时,就知道第一个数据包B已收到. 如果B没有收到第一次的数据包,那么B再收到A的数据包时,他就会发ack = 1回去,A收到B的回复,发现B没有收到第一次数据包,就会重发第一次数据包,这样就可以防止丢包.
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。完成三次握手,客户端与服务器开始传送数据.
网友评论