iOS面试问答集锦,从容应对各种面试技术难题!



原创: _小迷糊
Code4App 

序言

一个好的面试问题能使应聘者的本性显露出来——诚实,可信,反应敏锐等等。长期以来,我收集了一些自己在面试中总会用到的问题,这里整理出许多个最有价值的。希望这个总结能为面试官和应聘者提供一些参考,若你能轻而易举回答所有问题,面试就不必担心了。

面试题

1. http和scoket通信的区别?socket连接相关库,TCP,UDP的连接方法,HTTP的几种常用方式?

http和scoket通信的区别:

http是客户端用http协议进行请求,发送请求时候需要封装http请求头,并绑定请求的数据,服务器一般有web服务器配合(当然也非绝对)。 http请求方式为客户端主动发起请求,服务器才能给响应,一次请求完毕后则断开连接,以节省资源。服务器不能主动给客户端响应(除非采取http长连接技术)。iphone主要使用类是NSUrlConnection。 scoket是客户端跟服务器直接使用socket“套接字”进行连接,并没有规定连接后断开,所以客户端和服务器可以保持连接通道,双方都可以主动发送数据。一般在游戏开发或股票开发这种要求即时性很强并且保持发送数据量比较大的场合使用。主要使用类是CFSocketRef。

2.HTTP请求常用的几种方式

  • GET :获取指定资源
  • POST :2M  向指定资源提交数据进行处理请求,在RESTful 风格用于新增资源
  • HEAD :获取指定资源头部信息
  • PUT :替换指定资源(不支持浏览器操作)
  • DELETE: 删除指定资源

3.框架 SDWebimage的缓存机制

1.UIImageView+WebCache: setImageWithURL:placeholderImage:options: 先显示 placeholderImage ,同时由SDWebImageManager 根据 URL 来在本地查找图片。
2.SDWebImageManager: downloadWithURL:delegate:options:userInfo: SDWebImageManager是将UIImageView+WebCache同SDImageCache链接起来的类, SDImageCache: queryDiskCacheForKey:delegate:userInfo:用来从缓存根据CacheKey查找图片是否已经在缓存中
3.如果内存中已经有图片缓存, SDWebImageManager会回调SDImageCacheDelegate : imageCache:didFindImage:forKey:userInfo:
4.而 UIImageView+WebCache 则回调SDWebImageManagerDelegate:  webImageManager:didFinishWithImage:来显示图片。
5.如果内存中没有图片缓存,那么生成 NSInvocationOperation 添加到队列,从硬盘查找图片是否已被下载缓存。
6.根据 URLKey 在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调 
7.notifyDelegate:
8.如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:进而回调展示图片。
9.如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调 
10.imageCache:didNotFindImageForKey:userInfo:
11.共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。
12.图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。
13.connection:didReceiveData: 中利用 ImageIO 做了按图片下载进度加载效果。
14.connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。
15.图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。
16.在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给 SDWebImageDownloader。
17.imageDownloader:didFinishWithImage: 回调给 SDWebImageManager 告知图片下载完成。
18.通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。
19.将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。
20.写文件到硬盘在单独 NSInvocationOperation 中完成,避免拖慢主线程。
21.如果是在iOS上运行,SDImageCache 在初始化的时候会注册notification 到 UIApplicationDidReceiveMemoryWarningNotification 以及  UIApplicationWillTerminateNotification,在内存警告的时候清理内存图片缓存,应用结束的时候清理过期图片。
22.SDWebImagePrefetcher 可以预先下载图片,方便后续使用。

4.iOS App升级安装 - CoreData数据库升级

1.选中你的mydata.xcdatamodeld文件,选择菜单editor->Add Model Version  比如取名:mydata2.xcdatamodel2.设置当前版本3.修改新数据模型mydata2,在新的文件上添加字段及表4.删除原来的类文件,重新生成下类。在appdelegate中添加 *optionsDictionary,原来options:nil  改成options:optionsDictionary5.重新编译下程序。增加模型版本——->选择最新的版本——->选择表,添加字段——>删除之前的类,重新生成。

5.Objective-C堆和栈的区别?

管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。申请大小:栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因 此,能从栈获得的空间较小。堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。

6.AFN的实现原理AFN的直接操作对象AFHTTPClient不同于ASI,是一个实现了NSCoding和NSCopying协议的NSObject子类。 AFHTTPClient是一个封装了一系列操作方法的“工具类”,处理请求的操作类是一系列单独的,基于NSOperation封装 的,AFURLConnectionOperation的子类。AFN的示例代码中通过一个静态方法,使用dispatch_once()的方式创建 AFHTTPClient的共享实例,这也是官方建议的使用方法。在创建AFHTTPClient的初始化方法中,创建了OperationQueue并 设置一系列参数默认值。在getPath:parameters:success:failure方法中创建NSURLRequest,以 NSURLRequest对象实例作为参数,创建一个NSOperation,并加入在初始化发方中创建的NSOperationQueue。以上操作都 是在主线程中完成的。在NSOperation的start方法中,以此前创建的NSURLRequest对象为参数创建NSURLConnection 并开启连结。

7.imageName和ImageWithContextOfFile的区别?哪个性能高

  • 用imageNamed的方式加载时,图片使用完毕后缓存到内存中,内存消耗多,加载速度快。即使生成的对象被 autoReleasePool释放了,这份缓存也不释放,如果图像比较大,或者图像比较多,用这种方式会消耗很大的内存。imageNamed采用了缓存机制,如果缓存中已加载了图片,直接从缓存读就行了,每次就不用再去读文件了,效率会更高 。
  • ImageWithContextOfFile加载,图片是不会缓存的,加载速度慢。
  • 大量使用imageNamed方式会在不需要缓存的地方额外增加开销CPU的时间.当应用程序需要加载一张比较大的图片并且使用一次性,那么其实是没有必要去缓存这个图片的,用imageWithContentsOfFile是最为经济的方式,这样不会因为UIImage元素较多情况下,CPU会被逐个分散在不必要缓存上浪费过多时间.

还有很多的问题大家可以自己思考一下1.UIView的setNeedsDisplay和setNeedsLayout方法2.int和NSInteger的区别3.创建控制器、视图的方式4 简述内存分区情况5 iOS的系统架构6 控件主要响应3种事件7 简述视图控件器的生命周期。等等……

最后

没有人会讨厌和拒绝认真准备面试的人,所以不要认为面试就是必须用一个“素颜”的你去“真诚”的面对。


0