iOS面试题<二>

1.TCP三次握手,具体怎么交互?
- 第一次握手:
建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;

- 第二次握手:
服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;

- 第三次握手:
客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

- 三次握手的原因:
为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误, 造成服务器端的一直等待而浪费资源。如下:
“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

参考答案:
- 第一次握手:客户端发送syn(syn=j)包到服务器;并进入SYN_SEND-状态,等待服务器确认
- 第二次握手:服务器收到syn包,确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态
- 第三次握手**:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
- 注意:三次握手中发送的包不包含数据,三次握手完毕,客户端和服务器才正式开始传送数据。 TCP连接一旦建立,在通信双方的任何一方主动关闭连接之前,TCP连接都将被一直保持下去
2.什么是安全释放?
在对象被dealloc之后把指针置为nil.因为在OC中对nil发消息是安全的
注意: 空指针不是野指针!!

参考答案:对象被释放的时候,指向nil
3.在iphone上有两件事情要做,请问是在一个线程里按顺序做效率高还是两个线程里做效率高?为什么?
在不考虑内存瓶颈的前提下,两个线程里并发执行的效率高
这就好比,两件事都由一个人来做和两件相同的事情有两个不同人来做是一样, 人多分配任务,完成所需要的时间就少!

参考答案:如果两件事有依赖关系,事件二必须等到事件一执行完毕才执行,那么放在一个线程就可以了;
如果两者并没有什么关联,放到两个线程并发执行效率较高
4.NSArray和NSSet有何区别?
- NSArray是有序的,可以重复
- NSSet是无序的,不可以重复
- NSSet性能比NSArray性能高

参考答案:
- NSSet: 里面存放的元素是无序的,不重复的,可以通过anyObject来访问单个元素,
- NSArray : 里面存放的元素是有序的,可以有重复的对象,可以通过下标来访问里面的数组元素
在搜索一个一个元素时NSSet比NSArray效率高,主要是它用到了数据结构中的哈希算法,而NSArray则是需要遍历全部的数组元素,效率会低一些。
5.__weak什么时候用?
用于避免两个强引用产生的循环引用导致内存无法释放的问题
- weak: 用于对象类型, 由于 weak 同样不改变对象的引用计数且不持有对象实例, 当该对象废弃时, 该弱引用自动失效并且被赋值为 nil,所以它可以用于避免两个强引用产生的循环引用导致内存无法释放的问题.
- 定义: IBOutlet 控件属性一般也使用 weak;当然,也可以使用strong。在下文也有论述:《IBOutlet连出来的视图属性为什么可以被设置成weak?》
- 比如: delegate 代理属性, 就是为了避免循环引用.

参考答案:
当两个对象互相引用的时候,一端用strong,另一端必须用weak .例如: A拥有B, B也拥有A, 那么必须一方使用weak
一般UI控件都可以使用weak,因为自身已经对它进行一次强引用,没有必要再强引用一次.
6.列举几个常用集合类和存放二进制数据类?
不可变的数组--NSArray
可变的数组--NSMutableArray
不可变的字典--NSDictionary
可变的字典--NSMutableDictionary
不可变的集合--NSSet
可变的集合--NSMutableSet
缓存器--NSCache

二进制数据类—NSData

参考答案:
NSArray,NSDictionary,NSSet,以及他们的可变类
存放二进制的有NSData类
7.写出1-2个与动态调用有关的方法?
performSelector 相关
8.多线程,写出常用的几个类?
NSInvocationOperation
NSBlockOperation
NSOperationQueue
NSThread
NSRunloopRef

参考答案:
Pthread
NSThread
NSOperationQueue
GCD
9.一般在哪个函数中创建某个View的子view?
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. }

参考答案:
viewDidLoad 方法
10.什么是抽象类?有什么作用?能实例化吗?
NSOperation是一个抽象类,不能实例化,起作用的是它的子类:NSInvocationOperation
NSBlockOperation
自定义子类继承NSOperation,实现内部相应的方法

参考答案:
abstract修饰,它只能用来作父类,本身并没有生成实例的能力。它将一类最公有的属性和方法抽取出来 抽象类是将类共有的方法抽取出来,声明为抽象方法, 抽象方法只有声明没有具体的实现, 拥有抽象方法的类就是抽象类; 这样新增一种类型时候只需要继承抽象类,实现抽象方法就可以了,降低了实现新类的难度。
抽象方法修饰符 abstract 抽象类不能被实现如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
为什么要有抽象类?用于类型隐藏在面向对象领域,抽象类主要用来进行类型隐藏。我们可以构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类。用于拓展对象的行为功能. 这一组任意个可能的具体实现则表现为所有可能的派生类(子类),模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允许修改的;同时,通过从这个抽象体派生,也可扩展此模块的行为功能。
11.objc中向一个nil对象发送消息会发生什么?
在 Objective-C 中向 nil 发送消息是完全有效的——只是**在运行时不会有任何作用:

如果一个方法返回值是一个对象,那么发送给nil的消息将返回0(nil)。例如:

Person * motherInlaw = [[aPerson spouse] mother];`//如果 spouse 对象为 nil,那么发送给 nil 的消息 mother 也将返回 nil。

如果方法返回值为指针类型,其指针大小为小于或者等于sizeof(void*),float,double,long double 或者 long long 的整型标量,发送给 nil 的消息将返回0。
如果方法返回值为结构体,发送给 nil 的消息将返回0。结构体中各个字段的值将都是0。
如果方法的返回值不是上述提到的几种情况,那么发送给 nil 的消息的返回值将是未定义的。

objc在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实际所属的类,然后在该类中的方法列表以及其父类方法列表中寻找方法运行,然后在发送消息的时候,objc_msgSend方法不会返回值,所谓的返回内容都是具体调用时执行的。 那么,回到本题,如果向一个nil对象发送消息,首先在寻找对象的isa指针时就是0地址返回了,所以不会出现任何错误。
12.runloop和线程有什么联系?
总的说来:
1.Runloop,正如其名,loop表示某种循环,和run放在一起就表示一直在运行着的循环。实际上,runloop和线程是紧密相连的,可以这样说runloop是为了线程而生,没有线程,它就没有存在的必要。
2.Run loops是线程的基础架构部分, Cocoa 和 CoreFundation 都提供了 run loop 对象方便配置和管理线程的 run loop (以下都以 Cocoa 为例)。每个线程,包括程序的主线程( main thread )都有与之相应的 run loop 对象。
3.runloop 和线程的关系:主线程的runloop默认是启动的, 并且直到程序退出之前才会释放.
对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。

参考答案:
Runloop和线程的关系:一个Runloop对应着一条唯一的线程问题:如何让子线程不死回答:给这条子线程开启一个Runloop
Runloop的创建:主线程Runloop已经创建好了,子线程的runloop需要手动创建
Runloop的生命周期:在第一次获取时创建,在线程结束时销
13. 什么是懒汉模式,一般用在哪些地方?
懒加载模式:判断是否有值,有值的话就不用再重新创建;
如: view的加载,数据的加载

参考答案:
懒加载,指得是需要用到的时候才加载,其好处是节省内存空间,不必一开始就创建所有的变量,用到了就创建一块内存,同时也加快了程序运行速度.一般用于我们只需要创建一次的变量就可以的地方,例如字典转模型的数组,以及控制器的view等,都是懒加载的
14.常用的延时执行的几种方式?
1.GCD 的延迟执行** dispatch after 精确到纳秒 如: 3.0 * NSEC_PER_SEC == 3.0 * 10^9
2.NSTimer 定时器的延迟执行** 以秒为单位 如 1.0
3.CADisplayLink** 必须要把它添加到主循环当中 , 每秒60 次

参考答案:
perform selector
NSTimer
GCD:dispatch_after
15.写出你想到的设计模式,并简要描述?
1.代理模式:
代理遵守协议,将被代理对象的代理属性设置为自己,实现协议方法;被代理定义协议,定义被代理属性,调用代理方法

2.单例模式:
该工程内只能有该类的一个实例, 如:[NSUserDefaults standardUserDefaults],
[UIApplication sharedApplication],
[UIScreen mainScreen],
[NSFileManager defaultManager]

3.KVO模式(观察者模式):
一个对象的状态改变,通知正在对他进行观察的对象,这些对象根据各自要求作出相应的改变

4.MVC模式:
将工程的数据层,展示层,逻辑层分开, 又称 模型-视图-控制器(MVC), 是Cocoa的构建块之一,毫无疑问它是使用最频繁的设计模式。它根据通用的角色去划分类,这样就使得类的职责可以根据角色清晰的划分开来。

  Model:模型保存应用程序的数据,定义了怎么去操作它。例如在本应用中模型就是Album类。

  View:视图是模型的可视化表示以及用户交互的控件;基本上来说,所有的UIView对象以及它的子类都属于视图。在本应用中AlbumView代表了视图。

  Controller:控制器是一个协调所有工作的中介者(Mediator)。它访问模型中的数据并在视图中展示它们,同时它们还监听事件和根据需要操作数据。你可以猜猜哪个类是控制器吗?它正是:ViewController。

5.MVVM模式:
在MVVM中,我们将视图处理逻辑从C中剥离出来给V,剩下的业务逻辑部分被称做View-Model。
使用MVVM模式的iOS应用的可测试性要好于MVC,因为ViewModel中并不包含对View的更新,相比于MVC,减轻了Controller的负担,使功能划分更加合理。
MVVM模式的正确实践是,我们应该为app delegate的根视图创建一个ViewModel,当我们要生成或展示另一个次级ViewController时,采用当前的ViewModel为其创建一个子ViewModel。

参考答案:
1.单例模式:不管怎么创建,拿到的对象都是同一个
2.MVC:MVC把软件系统分为三个部分:Model,View,Controller。MVC有低耦合性、高重用性、可维护性等优点
3.代理模式:代理模式就是实现消息传递的一种机制,委托方有一些任务自己不想完成,但是还需要要实现,则将该任务存放到协议中,由代理完成.但是代理并不会主动的执行任务,需要委托方通知代理,然后代理完成委托方交给的任务.
4.观察者模式:经典观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己或者做出相应的一些动作。比如KVO,通知中心
16.是否使用过CoreText或者CoreImage等?如果使用过,请谈谈你使用CoreText或者CoreImage的体验?
CoreText
不带图片的排版引擎,CoreText实际上并没有相应API直接将一个图片转换为CTRun并进行绘制,它所能做的只是为图片预留相应的空白区域,而真正的绘制则是交由CoreGraphics完成,在CoreText中提供了CTRunDelegate这么个Core Foundation类,顾名思义它可以对CTRun进行拓展:AttributedString某个段设置kCTRunDelegateAttributeName属性之后,CoreText使用它生成CTRun是通过当前Delegate的回调来获取自己的ascent,descent和width, 而不是根据字体信息。这样就给我们留下了可操作的空间:用一个空白字符作为图片的占位符,设好Delegate,占好位置,然后用CoreGraphics进行图片的绘制。

CoreImage
苹果自有框架不仅可以做图片处理,还可以做人脸识别等多种工作,CIImage是CoreImage框架中最基本代表图像的对象,他不仅包含元图像数据,还包含作用在原图像上的滤镜链。

CIFilter
用来表示CoreImage提供的各种滤镜。滤镜使用键-值来设置输入值,一旦这些值设置好,CIFilter就可以用来生成新的CIImage输出图像了。这里的输出的图像不会进行实际的图像渲染,他只包含一个对输入图像的引用以及需要应用与数据上的滤镜链。IOS永远在最佳的时间选择渲染图像。

参考答案:
1.CoreText:是用于处理文字和字体的底层技术。Quartz 能够直接处理字体(font)和字形(glyphs),将文字渲染到界面上,它是基础库中唯一能够处理字形的模块。因此,CoreText 为了排版,需要将显示的文本内容、位置、字体、字形直接传递给 Quartz。相比其它 UI 组件,由于 CoreText 直接和 Quartz 来交互,所以它具有高速的排版效果。
2.coreImage:是IOS5中新加入的一个Objective-c的框架,提供了强大高效的图像处理功能,用来对基于像素的图像进行操作与分析. iOS提 供了很多强大的滤镜(Filter),其中IOS5中有48种,而到了最新的IOS6 Filter已经增加到了93种之多,并且这一数字会继续增加。这些Filter提供了各种各样的效果,并且还可以通过滤镜链将各种效果的Filter叠 加起来,形成强大的自定义效果,如果你对该效果很满意,还可以子类化滤镜
17.POST. GET的区别?
GET 方法:GET 方法提交数据不安全,数据置于请求行,客户端地址栏可见;
GET 方法提交的数据大小有限
GET 方法不可以设置书签

POST 方法:POST 方法提交数据安全,数据置于消息主体内,客户端不可见
POST 方法提交的数据大小没有限制
POST 方法可以设置书签

参考答案:
POST:将参数放在请求体中,参数的大小原则上没有限制一般传输的数据包含隐私相关的用POST
GET:将参数附加在URL后面,因为URL长度的限制,所以参数的大小是有限制的,通常不能超过1KB GET 在请求URL后面以?的形式跟上发给服务器的参数,多个参数之间用&隔开

版权归属于离离离离。
版权所有,翻版必究,如若转载,请注明出处。谢谢 ~

你可能感兴趣的:(iOS面试题<二>)