< 返回首页

标哥的笔记,是记录在日常学习技术和日常开发中那些年遇到过的坑!本站为新站,原"标哥的技术博客"中的文章会慢慢移到本站,欢迎收藏本站!
在使用本站过程中,有任何建议请联系标哥! 另,承接App开发、网站开发和微信小程序开发!欢迎联系我们


iOS中级面试题二

 作者:标哥    发布日期:2017-01-12 15:22    阅读量:1275次
 

本篇文章中所收集的面试题大部分来源来网络,小部分为笔者根据个人经验所出的面试题。所有题目都会提供参考答案,但是参考答案仅供参考,不保证一定正确,且答案不是唯一的,不同的面试官的知识面和技术水平不同也会出现不同的意见。

如果没有阅读过前一份中级面试题【iOS中级面试题一】,可以先阅读之。

题目解答

1、iOS数据持久化存储方案有哪些?

参考答案:

  1. plist属性列表存储(如NSUserDefaults)

  2. 文件存储(如二进制数据写入文件存储,通过NSFileManager来操作将下载起来的二进制数据写一篇文件中存储)

  3. NSKeydeArchiver归档存储,常见的是自动化归档/解档处理,想要学习如何通过runtime实现自动化归档/解档,可以阅读文章:学习通过runtime实现自动化归档/解档

  4. 数据库SQLite3存储(如FMDB、Core Data)

2、沙盒的目录结构是怎样的?各自一般用于什么场合?

参考答案:

  1. Application:存放程序源文件,上架前经过数字签名,上架后不可修改

  2. Documents: 保存应⽤运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录

  3. tmp: 保存应⽤运行时所需的临时数据,使⽤完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时 不会备份该目录 

  4. Library/Caches: 保存应用运行时⽣成的需要持久化的数据,iTunes同步设备时不会备份该目录。⼀般存储体积大、不需要备份的非重要数据,比如网络数据缓存存储到Caches下 

  5. Library/Preference: 保存应用的所有偏好设置,如iOS的Settings(设置) 应⽤会在该目录中查找应⽤的设置信息。iTunes同步设备时会备份该目录

3、#define定义的宏和const定义的常量有什么区别?

参考答案:

  1. #define定义宏的指令,程序在预处理阶段将用#define所定义的内容只是进行了替换。因此程序运行时,常量表中并没有用#define所定义的宏,系统并不为它分配内存,而且在编译时不会检查数据类型,出错的概率要大一些。

  2. const定义的常量,在程序运行时是存放在常量表中,系统会为它分配内存,而且在编译时会进行类型检查。

  3. #define定义表达式时要注意“边缘效应”,例如如下定义:

#define N 2 + 3 // 我们预想的N值是5,我们这样使用N
int a = N / 2;  // 我们预想的a的值是2.5,可实际上a的值是3.5

4、常见的出现内存循环引用的场景有哪些?

参考答案:

  1. 定时器(NSTimer):NSTimer经常会被作为某个类的成员变量,而NSTimer初始化时要指定self为target,容易造成循环引用(self->timer->self)。 另外,若timer一直处于validate的状态,则其引用计数将始终大于0,因此在不再使用定时器以后,应该先调用invalidate方法

  2. block的使用:block在copy时都会对block内部用到的对象进行强引用(ARC)或者retainCount增1(非ARC)。在ARC与非ARC环境下对block使用不当都会引起循环引用问题, 一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.someBlock = Type var{[self dosomething];或者self.otherVar = XXX;或者_otherVar = …};出现循环的原因是:self->block->self或者self->block->_ivar(成员变量)

  3. 代理(delegate):在委托问题上出现循环引用问题已经是老生常谈了,规避该问题的杀手锏也是简单到哭,一字诀:声明delegate时请用assign(MRC)或者weak(ARC),千万别手贱玩一下retain或者strong,毕竟这基本逃不掉循环引用了!

5、block中的weak self,是任何时候都需要加的么?

参考答案:

不是什么任何时候都需要添加的,不过任何时候都添加似乎总是好的。只要出现像self->block->self.property/self->_ivar这样的结构链时,才会出现循环引用问题。好好分析一下,就可以推断出是否会有循环引用问题。

6、GCD的queue、main queue中执行的代码一定是在main thread么?

参考答案:

  1. 对于queue中所执行的代码不一定在main thread中。如果queue是在主线程中创建的,那么所执行的代码就是在主线程中执行。如果是在子线程中创建的,那么就不会在main thread中执行。

  2. 对于main queue就是在主线程中的,因此一定会在主线程中执行。获取main queue就可以了,不需要我们创建,获取方式通过调用方法dispatch_get_main_queue来获取。

7、头文件中声明的成员变量(不是属性),外部可直接访问么?

参考答案:

外部不能直接访问头文件所声明的成员变量,需要提供成员变量的getter方法才能在外部访问。而属性已经直接给我们自动生成了getter方法,因此外部可以直接访问属性。

8、TCP和UDP的区别是什么?

参考答案:

  1. TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序传输)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。

  2. UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快,传输的是报文。

3#9、MD5和Base64的区别是什么,各自使用场景是什么?

参考答案:

做过加密相关的功能的,几乎都会使用到MD5和Base64,它们两者在实际开发中是最常用的。

  1. MD5:是一种不可逆的摘要算法,用于生成摘要,无法逆着破解得到原文。常用的是生成32位摘要,用于验证数据的有效性。比如,在网络请求接口中,通过将所有的参数生成摘要,客户端和服务端采用同样的规则生成摘要,这样可以防篡改。又如,下载文件时,通过生成文件的摘要,用于验证文件是否损坏。

  2. Base64:属于加密算法,是可逆的,经过encode后,可以decode得到原文。在开发中,有的公司上传图片采用的是将图片转换成base64字符串,再上传。在做加密相关的功能时,通常会将数据进行base64加密/解密。

10、发送10个网络请求,然后再接收到所有回应之后执行后续操作,如何实现?

参考答案:

从题目分析可知,10个请求要全部完成后,才执行某一功能。比如,下载10图片后合成一张大图,就需要异步全部下载完成后,才能合并成大图。

做法:通过dispatch_group_t来实现,将每个请求放入到Group中,将合并成大图的操作放在dispatch_group_notify中实现。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{ /*加载图片1 */ });
dispatch_group_async(group, queue, ^{ /*加载图片2 */ });
dispatch_group_async(group, queue, ^{ /*加载图片3 */ }); 
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // 合并图片
});

11、__block和__weak修饰符的区别?

参考答案:

  1. __block不管是ARC还是MRC模式下都可以使用,它的作用是标识block外的变量在block内使用可以修改变量的值。

  2. __weak只能在ARC模式下使用,表示弱引用,主要是用于防止循环引用而引入的。

12、常见的Http状态码有哪些?

参考答案:

  1. 302是请求重定向。

  2. 500及以上是服务器错误,如503表示服务器找不到、3840表示服务器返回无效JSON。

  3. 400及以上是请求链接错误或者找不到服务器,如常见的404。

  4. 200及以上是正确,如常见的是200表示请求正常。

  5. 100及以上是请求接受成功。

更详细请阅读:Http状态码详细说明

13、iOS与H5交互的方式有哪些?

参考答案:

  1. 通过协议在shouldStartRequest中捕获请求,获取scheme来判断预先定义的功能,然后调用native代码。比如,定义点击图片调用native来展示大图,那么js接收到点击时,重定向将图片的url添加上自定义scheme,如HYBImagePreview://这样。

  2. 通过iOS7以后引入的JavascriptCore框架来实现,通过注入对象的方式来实现,维护起来更简单。更详细请阅读我的文章:Oc版本与JS交互、如何使用的是WKWebView,可阅读WKWebView与JS交互

  3. 通过WebViewJavascriptBridge这个第三方库来实现,看WebViewJavascriptBridge的详细使用

14、如何浅拷贝与深拷贝的理解?

参考答案:

所谓浅拷贝是指只复制指向对象的指针,而不复制引用对象本身(同一份内存),而所谓深拷贝是指复制引用对象本身(新创建了一份内存)。

打个比方:

浅复制好比是你的影子,当你挂了,影子也消失了。 深复制好比克隆你,即使你挂了,新克隆出来的人是新的生命,不会因为你挂了也跟着挂。

15、什么是懒加载?常见场景?

参考答案:

所谓懒加载是指在真正需要到的时候才真正载入内存。常见的场景就是重写属性的getter方法,在getter方法中判断是否创建过或者加载过,若未创建过或者未加载过,则创建或者加载。

懒加载可以优化性能,有的功能一般情况下不会使用到,但是这些功能一使用就会占较大的内存,此时使用懒加载就非常的好了。

常见的写法:

- (NSMutableArray *)dataSource {
  if (_dataSource == nil) {
    _dataSource = [[NSMutableArray alloc] init];
    // 添加默认数据等
    // ...
  }
}

16、一个tableView是否可以关联两个不同的数据源?

参考答案:

当然是可以关联多个不同的数据源,但是不同同时使用多个数据源而已。比如,一个列表有两个筛选功能,一个是筛选城市,一个是筛选时间,那么这两个就是两个数据源了。当筛选城市时,就会使用城市数据源;当筛选时间时,就会使用时间数据源。

17、对象添加到通知中心中,当通知中心发通知时,这个对象却已经被释放了,可能会出现什么问题?

参考答案:

其实这种只是考查对通知的简单应用。通知是多对多的关系,主要使用场景是跨模块传值。当某对象加入到通知中心后,若在对象被销毁前不将该对象从通知中心中移除,当发送通知时,就会造成崩溃。这是很常见的。所以,在添加到通知中心后,一定要在释放前移除。

18、实现过框架或者库以供他人使用么?如果有,请谈一谈构建框架或者库时候的经验;如果没有,请设想和设计框架的public的API,并指出大概需要如何做、需要注意哪些问题,以使人人更容易地使用你的框架。

参考答案:

实现过的。本人开源过多个组件的,可到GITHUB查找:标哥的GITHUB开源组件库,每个开源组件都有详细的博文说明如何使用哦。当然,在公司也设计了相关的公共框架,不可公开!从以下角度出发来思考和设计公共框架:

  1. 确保外部调用简单,且保证有详细的头文件注释说明。

  2. 确保API编码规范,保证风格统一。

  3. 确保API易扩展,可以考虑预留参数

  4. 确保没有外部依赖或者依赖要尽可能的少,以保证公共库的纯洁(原则上不能有外部依赖)

  5. 确保易维护,不存在冗余API

19、如何自动计算cell的高度?

参考答案:

笔者喜欢纯代码自动布局,一直使用Masonry这个第三方库来实现纯代码自动布局的,使用起来非常简单,而且效率也很高。开发起来,提高了开发效率。

关于Masonry自动计算行高,笔者提供了swift版和oc版本的扩展,这两个版本都提供了自动计算行高的功能,并且带有缓存功能,保证永远只计算一次行高,效率就会很高,一般的应用也就不会卡屏了。

学习OC版本自动计算行高扩展

实现原理:通过数据模型的id作为key,以确保唯一,如何才能保证复用cell时不会出现混乱。在配置完数据后,通过更新约束,得到最后一个控件的frame,就只可以判断cell实际需要的高度,并且缓存下来,下次再获取时,判断是否存在,若存在则直接返回。因此,只会计算一遍。

20、UITableView是如何计算内容高度的?为什么初始化配置数据时,获取行高的代理方法会调用数据条数次?

参考答案:

UITableView是继承于UIScrollView的,因此也有contentSize。要得到tableview的contentsize,就需要得到所有cell的高度,从而计算出总高度,才能得到contentsize。因此,在reloadData时,就会调用该代理方法数据条数次。

为了提高效率,笔者写了扩展用于自动计算行高的,并且带有缓存,以保证只会计算一次,防止卡屏。做到这一点,一般的应用就可以解决卡屏的问题了。对于富文本比较多的应用,还可以继续优化哦。

结尾

所有参考答案都是笔者亲自一字一句敲出来的,都是根据笔者的情况而写的参考答案,不具有代表性,仅供参考。若有错误,请大家在评论中指出,谢谢!


承接:ThinkPHP项目开发、网站项目开发、微信项目开发、微信小程序项目开发、App开发,欢迎联系标哥QQ632840804