< 返回首页

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


iOS中级面试题一

 作者:标哥    发布日期:2017-01-12 14:06    阅读量:859次
 

半年前在知乎浏览到一个帖子,是关于如何面试iOS工程师。由于当时公司正在招聘iOS工程师,自己也面试了不少同学,就饶有兴致的把自己的面试问题清单贴了出去,却意外的引来了不少关注。还有不少同学认真回答并将答案私信于我交流的,还有求隐藏关卡的。由于工作太忙,私信和评论后面都没怎么回复,这里一并做下总结回复。(来源于知乎)

一份面试题的意义

我把收到的私信和一百多条评论都仔细读了遍,发现大家之所以会关注大致出于以下几个原因:

刚毕业的同学最近在找工作面试,想实现题增加面试通过率。 有一定的工作经历的同学,想测试下自己的iOS水平,看自己能卖多少钱。 本身iOS基础不错,抱着技多不压身心态补充知识的。 土豪老板就差一个程序员了,想找份带标准答案的面试题找真爱。

除了第三类同学心态正确外,其他的都高估面试题的作用了。面试题只是武功招式,知识体系才是内功心法。刚入门记住的都是招式,但招式何其多,面试的时候总会有遗漏和盲区,内功心法才是一通万通,能以不变应万变。这份面试题你答不全不能说明你iOS不及格,你全答对了你也不能上天。真正应该关注的是这份题背后所包含的理论知识体系。帖子里还有其他不少优质回答,涵盖候选人心态,习惯,基础知识,产品理解等各个方面,都值得一读。当然啦,既然出了题,就得有答案,就有它的目标群体。主要考察对象是从事iOS开发 1~3年的同学。不需要全部答对,能对一半以上问题侃侃而谈就不错了。

评论区百态

评论区有各路神仙吐槽,有的说难,有的说太容易,还有美工和安卓党出现。大家七嘴八舌的讨论意见很杂,但从中可以看出不少同学心态都不正确。技术这条路无穷无尽,广度和深度的拓展都需要长年累月的积累,不存在什么够用就好了,用的时候再查下,没必要了解这么深。技术人员的视野和耐力决定在这条路上你能够走多远。下面几类同学点名批评:

  1. 故作无知都机灵的。

  2. 觉得sqlite太重没必要用的。

  3. 说太容易不愿意答题的。

  4. 说都不会但不影响做项目的。

  5. 说圆角头像让美工切个图就搞定的。

  6. 说一半不会没必要深究的。

  7. 心态不及格。

合格的答案

出乎我意料之外的是有好几位同学都正二八经的答了题,还把答案私信了我。这里贴出其中一份答得还不错的,再后面是答主自己的答案。 过关回答

我的答案

我有过不少面试和被面试的经历,作为面试官出这份面试题从来就不是为了难倒面试者,而是为了多角度全面的了解面试者从而建立信任。面试的时候最担心的是冷场,面试题只不过个引子,我心底里最希望遇到的面试者是能够举一反三,除了回答问题本身之外,还能自信的旁征博引,深谈其背后原理或者相关的知识理论的。问题本身反而并不怎么重要。这份清单里的问题也并不难,这里我列下我的回答以及从我的角度所期望的答案。

什么是arc?(arc是为了解决什么问题诞生的?)

现在有不少程序员是直接从arc上手的,从没接触过mrc,对arc的理解仅仅停留在apple帮助管理内存的层面。这个问题真正想了解的是对内存管理的理解,retain release虽然不用写了,但arc下还是会有内存泄漏野指针crash的bug存在。如果能从retain count这种内存管理策略的角度去阐述arc诞生的意义就算答对了。如果还能扯下其他类型的策略,比如java里的mark and sweep,那就加分点赞。

请解释以下keywords的区别: assign vs weak, __block vs __weak

这道题属于基础语法题,可以网上搜到答案。不过真有不少同学不知道weak在对象释放后会置为nil。__block关键字的理解稍微难点,因为在arc和mrc下含义(对retain count的影响)完全不同。理解了这几个关键字就能应付使用block时引入retain cycle的风险了。这题还在内存管理的范畴之内。

使用atomic一定是线程安全的吗?

看这题的问法不用想答案肯定是NO。有些人说不出所以然,有些人知道通过property的方式使用才能保证安全,还有人知道这个用来做多线程安全会有性能损耗,更有出色的候选人能谈atomic,synchronized,NSLock,pthread mutex,OSSpinLock的差别。好奇宝宝点我

描述一个你遇到过的retain cycle例子。(别撒谎,你肯定遇到过)

说没遇到过的我很难相信你有过成熟项目的经历。这题答不出了会扣很多很多分。用过block,写过delegate的肯定都踩过坑。

+load和+initialize有什么用处?

这题属于runtime范畴,我遇到过能说出对runtime的理解却不知道这两个方法的候选人。所以答不出来也没关系,这属于细节知识点,是加分项,能答出两个message各在什么阶段接收就可以了。

  1. +load是在类载入时就会调用。通常我们在Method-Swizzling时,会选择在+load方法中处理。因为只要类存在,就会载入,而只要载入就会调用。

  2. +initialize是在类首次被调用时才会调用,所以即使类存在并不一定会调用

为什么其他语言里叫函数调用, objective c里则是给对象发消息(或者谈下对runtime的理解)

这题考查的是objective c这门语言的dynamic特性,需要对比c++这类传统静态方法调用才能理解。最好能说出一个对象收到message之后的完整的流程是如何的。对runtime有完整理解的候选人还能说出oc的对象模型。

  1. 首先,函数调用通常是在面向过程的语言中叫法。

  2. 其次,ObjC是扩展C,因此具备C的特性,也就有函数调用

  3. 最后,ObjC中有面向对象特性,在编译时会将方法调用转成成objc_msgSend,其实就是给消息接收者发送消息。

什么是method swizzling?

说了解runtime但没听过method swizzling是骗人的。这题很容易搜到答案。定位一些疑难杂症bug,hack老项目实现,阅读第三方源码都有机会接触到这个概念。

Method-Swizzling其实就是方法实现体交换。在ObjC中,方法名与实现体是一一对应的关系,只要知道方法名,就能找到实现体。

笔者专门学习研究了一下runtime的Method-Swizzling,大家可以参考阅读Runtime Method Swizzling

UIView和CALayer是啥关系?

能答出UIView是CALayer的delegate就及格了,能说出UIView主要处理事件,CALayer负责绘制就更好,再聊下二者在使用过程中对动画流畅性影响的注意点就更好了,UI流畅性是个大话题。

一个UIView默认会有一个layer,当然一个UIView可以有很多个layer。UIView负责处理事件,而CALayer负责绘制,而绘制渲染又分为离屏渲染和当前屏渲染。我们知道,离屏渲染是要付出很大的代价的,因此在性能方面是需要好好考虑的。

如何高性能的给UIImageView加个圆角?

这题讨论的最多,还有说美工切图就搞定的。答主在项目里做过圆角头像的处理,里面的坑还真不少。cornerRadius会导致offscreen drawing有性能问题,美工切图无法适用有背景图的场景,即使加上shouldRasterize也有cache实效问题。正确的做法是切换到工作线程利用CoreGraphic API生成一个offscreen UIImage,再切换到main thread赋值给UIImageView。这里还涉及到UIImageView复用,圆角头像cache缓存(不能每次都去绘制),新旧头像替换等等逻辑。还有其他的实现方式,但思路离不开工作线程与主线程切换。

使用drawRect有什么影响?(这个可深可浅,你至少得用过。。)

不少同学都用过drawRect或者看别人用过,但不知道这个api存在的含义。这不仅仅是另一种做UI的方式。drawRect会利用CPU生成offscreen bitmap,从而减轻GPU的绘制压力,用这种方式绘制UI可以将动画流畅性优化到极致,但缺点是绘制api复杂,offscreen cache增加内存开销。UI动画流畅性的优化主要平衡CPU和GPU的工作压力。

ASIHttpRequest或者SDWebImage里面给UIImageView加载图片的逻辑是什么样的?

很多同学没有读源码的习惯,别人的轮子拿来只是用用却不知道真正的营养都在源代码里面。这两个经典的framework代码并不复杂,很值得一读。能对一个UIImageView怎么通过url展示一张图片有完整的理解。涉及到的知识点也非常多,UITableViewCell的复用,memory cache, disk cache, 多线程切换,甚至http协议本身都需要有一定的涉及。

把UIImageView放到UITableViewCell里面问更赞。

麻烦你设计个简单的图片内存缓存器(移除策略是一定要说的)

内存缓存是个通用话题,每个平台都会涉及到。cache算法会影响到整个app的表现。候选人最好能谈下自己都了解哪些cache策略及各自的特点。常见的有FIFO,LRU,LRU-2,2Q等等。由于NSCache的缓存策略不透明,一些app开发者会选择自己做一套cache机制,其实并不难。

讲讲你用Instrument优化动画性能的经历吧(别问我什么是Instrument)

Apple的instrument为开发者提供了各种template去优化app性能和定位问题。很多公司都在赶feature,并没有充足的时间来做优化,导致不少开发者对instrument不怎么熟悉。但这里面其实涵盖了非常完整的计算机基础理论知识体系,memory,disk,network,thread,cpu,gpu等等,顺藤摸瓜去学习,是一笔巨大的知识财富。动画性能只是其中一个template,重点还是理解上面问题当中CPU GPU如何配合工作的知识。

loadView是干嘛用的?

不要就简单的告诉我没用过,至少问下我有什么用。。这里是apple给开发者自己设置custom view的位置。说UI熟悉的一定要知道。

viewWillLayoutSubView你总是知道的。。

controller layout触发的时候,开发者有机会去重新layout自己的各个subview。说UI熟悉的一定要知道。

GCD里面有哪几种Queue?你自己建立过串行queue吗?背后的线程模型是什么样的?

两种queue,串行和并行。main queue是串行,global queue是并行。有些开发者为了在工作线程串行的处理任务会自己建立一个serial queue。背后是苹果维护的线程池,各种queue要用线程都是这个池子里取的。GCD大家都用过,但很多关键的概念不少人都理解的模凌两可。串行,并行,同步,异步是GCD的核心概念。

用过coredata或者sqlite吗?读写是分线程的吗?遇到过死锁没?咋解决的?

没用过sqlite是说不过去的。用过CoreData的肯定有很多血泪史要说。多谢线程模型你肯定做过比较选择。死锁是啥肯定也是要知道的,没遇到过至少能举个简单的例子来说明。单个线程可以死锁(main thread里dispatch_sync到main queue),多个线程直接也可以死锁(A,B线程互相持有对方需要的资源且互相等待)。

http的post和get啥区别?(区别挺多的,麻烦多说点)

这个可以说很多。不希望听到的答案有

两个差不多,随便用一个。 post比get安全(其实两个都不安全) 能说下两个http格式有什么不同,各自应用的场景就合格了。

结尾

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


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