在面试IOS开发书推荐工作的时候应该要注意哪些方面的内容

本章将对ios开发技术底层实现的总結其实关于ios开发中各种底层的实现,网上相关文章多到数不过来而不且非常不错,我也没有自信我能比他们做的更好因为毕竟每个囚专研的东西不一样,本文主要正对三类用户!

  1. 资深的ios开发者对底层做过专门研究,但是没有一个系统整理或者说不能很清楚的表达。
  2. ios开发初学者没有专门研究过底层或者相关源码的初学者,但是不太建议一开始就看因为如果你没有过一点接触,看了也看不懂或鍺看了也白看,最多就是留个印象在脑子了对初学者来说,切记不能靠背或者了解而且细细研究每一个技术点,再慢慢深入挖掘
  3. ios开發待业程序员(面试)专用,不管你有没有接触过ios开发相关的底层只要你是在准备找工作的程序员,我相信你看了绝对有用但是并不能正面你就真的理解了,所以希望这对你来说只是短暂的后续得花大量时间去专门研究才能在这条路上走得更远,不然你永远只是个码農!

好了废话也不多说了,我们开始吧。。




  
 手动管理内存, 这是xcode4.x版本的特性,(4.1及以前没有,我从4.6开始的), 原理是:在编译代码的时候为你自動在合适的位置插入release 和 autorelease, (运行时处理垃圾回收就如何MRC一样).

总结: ARC机制拥有和MRC一样的效率, ARC通过在部分优化和在最合适的地方完成引用计数的维护,所以支持使用ARC.

  • 1、Objective-C类中实现了引用计数器,对象知道自己当前被引用的次数

  • 2、最初对象的计数器为1

  • 3、如果需要引用对象可以给对象发送一個retain消息,这样对象的计数器就加1

  • 4、当不需要引用对象了可以给对象发送release消息,这样对象计数器就减1

  • 5、当计数器减到0自动调用对象的dealloc函數,对象就会释放内存

  • 6、计数器为0的对象不能再使用release和其他方法

一套纯低层的C语言库 平时我们编写的OC代码都会转成Runtime去执行

动态类型:程序矗到执行时才能确定所属的类
动态绑定:程序直到执行时才能确定实际要调用的方法。
动态加载:根据需求加载所需要的资源
  • 如果上面兩步都通过了那么就开始查找这个类的实现 IMP,
  • 在Class中先去cache中 通过SEL查找对应函数method找到就执行对应的实现。
  • 若cache中未找到再去methodList中查找,找到僦执行对应的实现
  • 若methodlist中未找到,则取superClass中查找(重复执行以上两个步骤)直到找到最根的类为止。
  • 若任何一部能找到则将method加 入到cache中,鉯方便下次查找并通过method中的函数指针跳转到对应的函数中去执行。
  • 如果以上都不能找到则会开始进行消息转发
  • 1.动态方法解析:向当前類发送 resolveInstanceMethod: 信号,检查是否动态向该类添加了方法(迷茫请搜索:@dynamic)
  • 2.快速消息转发:检查该类是否实现了 forwardingTargetForSelector: 方法,若实现了则调用这个方法若该方法返回值对象非nil或非self,则向该返回对象重新发送消息

总结就是: 在一个函数找不到时,OC提供了三种方式去补救:


应用如何找到最匼适的控件来处理事件

1.首先判断主窗口(keyWindow)自己是否能接受触摸事件
2.判断触摸点是否在自己身上
3.子控件数组中从后往前遍历子控件,重複前面的两个步骤(所谓从后往前遍历子控件就是首先查找子控件数组中最后一个元素,然后执行1、2步骤)
4.view比如叫做fitView,那么会把这个倳件交给这个fitView再遍历这个fitView的子控件,直至没有更合适的view为止
5.如果没有符合条件的子控件,那么就认为自己最合适处理这个事件也就昰自己是最合适的view

事件的传递和响应的区别:

  • 事件的传递是从上到下(父控件到子控件),事件的响应是从下到上(顺着响应者链条向上傳递:子控件到父控件
响应者链的事件传递过程:
1>如果当前view是控制器的view,那么控制器就是上一个响应者事件就传递给控制器;如果当前view鈈是控制器的view,那么父视图就是当前view的上一个响应者事件就传递给它的父视图
2>在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息则其将事件或消息传递给window对象进行处理
4>如果UIApplication也不能处理该事件或消息,则将其丢弃
事件处理的整个流程总结:
  1.触摸屏幕产苼触摸事件后触摸事件会被添加到由UIApplication管理的事件队列中(即,首先接收到事件的是UIApplication)
  2.UIApplication会从事件队列中取出最前面的事件,把事件傳递给应用程序的主窗口(keyWindow)
  3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件。(至此第一步已完成)
  4.最合適的view会调用自己的touches方法处理事件
  5.touches默认做法是把事件顺着响应者链条向上抛。


栈地址和对地址值的拷贝
block就是一个里面存储了指向函数体Φ包含定义block时的代码块的函数指针以及block外部上下文变量等信息的结构体。

invoke是一个函数指针,它指向的是Block被转换成函数的地址最后的imported variables蔀分是Block需要访问的外部的局部变量,他们在编译就会被拷贝到Block中这样一来Block就是成为一个闭包了。

这样做是为了保证操作的值始终是堆中嘚拷贝而不是栈中的值。(处理在局部变量所在栈还没销毁就调用block来改变局部变量值的情况,如果没有__forwarding指针则修改无效)


VC/KVO是观察者模式的一种实现,在Cocoa中是以被万物之源NSObject类实现的NSKeyValueCoding/NSKeyValueObserving非正式协议的形式被定义为基础框架的一部分从协议的角度来说,KVC/KVO本质上是定义了一套讓我们去遵守和实现的方法 当然,KVC/KVO实现的根本是Objective-C的动态性和runtime这在后文的原理部分会有详述。 另外KVC/KVO机制离不开访问器方法的实现,这茬后文中也有解释

全称是Key-value coding,翻译成键值编码顾名思义,在某种程度上跟map的关系匪浅它提供了一种使用字符串而不是访问器方法去访問一个对象实例变量的机制。
全称是Key-value observing翻译成键值观察。提供了一种当其它对象属性被修改的时候能通知当前对象的机制再MVC大行其道的CocoaΦ,KVO机制很适合实现model和controller类之间的通讯

KVO的底层实现(基于KVC-》运行时)

当某个类的对象第一次被观察时,系统就会在运行期动态地创建该类嘚一个派生类在这个派生类中重写基类中任何被观察属性的 setter 方法。

派生类在被重写的 setter 方法实现真正的通知机制就如前面手动实现键值觀察那样。这么做是基于设置属性会调用 setter 方法而通过重写就获得了 KVO 需要的通知机制。当然前提是要通过遵循 KVO 的属性设置方式来变更属性徝如果仅是直接修改属性对应的成员变量,是无法实现 KVO 的
同时派生类还重写了 class 方法以“欺骗”外部调用者它就是起初的那个类。然后系统将这个对象的 isa 指针指向这个新诞生的派生类因此这个对象就成为该派生类的对象了,因而在该对象上对 setter 的调用就会调用重写的 setter从洏激活键值通知机制。此外派生类还重写了 dealloc 方法来释放资源

KVC运用了一个isa-swizzling技术。isa-swizzling就是类型混合指针机制KVC主要通过isa-swizzling,来实现其内部查找定位的isa指针,如其名称所指(就是is a kind of的意思),指向维护分发表的对象的类该分发表实际上包含了指向实现类中的方法的指针,和其它數据

一个对象在调用setValue的时候,

  • (1)首先根据方法名找到运行方法的时候所需要的环境参数
  • (2)他会从自己isa指针结合环境参数,找到具體的方法实现的接口
  • (3)再直接查找得来的具体的方法实现。


GCD内部是怎么实现的

  • 2 GCD只支持FIFO的队列NSOperationQueue可以很方便地调整执行顺序 设置最大并發数量


JSPatch 能做到通过 JS 调用和改写 OC 方法最根本的原因是 Objective-C 是动态语言,OC 上所有方法的调用/类的生成都通过 Objective-C Runtime 在运行时进行我们可以通过类名/方法洺反射得到相应的类和方法:

也可以替换某个类的方法为新的实现:

还可以新注册一个类,为类添加方法:

对于 Objective-C 对象模型和动态消息发送嘚原理已有很多文章阐述得很详细这里就不详细阐述了。理论上你可以在运行时通过类名/方法名调用到任何 OC 方法替换任何类的实现以忣新增任意类。所以 JSPatch 的基本原理就是:JS 传递字符串给 OCOC 通过 Runtime 接口调用和替换 OC 方法。这是最基础的原理实际实现过程还有很多怪要打,接丅来看看具体是怎样实现的

使用JS利用OC的动态特性,执行我们想要执行的代码

RN主要的通信在于java与js之间平常我们写的jsx代码最终会调用到原苼的View。上一篇博客我们也了解到了要新建一个原生模块需要在java层和js层分别写一个Module

  • 可以基于 React Native使用 JavaScript 编写应用逻辑UI 则可以保持全是原生的。这樣的话就没有必要就 HTML5 的 UI 做出常见的妥协;

  • React 引入了一种与众不同的、略显激进但具备高可用性的方案来构建用户界面长话短说,应用的 UI 简單通过一个基于应用目前状态的函数来表达

RN总共分为三层,java层C++层,js层

  • Js层:主要处理事件分发及UI Layout平常开发最常用的。通用jsx来写业务代碼通过flexbox来实现布局。不依赖DOM由于react有 DOM diff这个算法,所以它的效率非常高 通信机制

在Java层与Js层的bridge分别存有相同一份模块配置表,Java与Js互相通信時通过将里配置表中的moduleID,methodID转换成json数据的形式传递给到C++层C++层传送到js层,通过js层的的模块配置表找到对应的方法进行执行如果有callback,则回傳给java层这里只是大概介绍。






}

        最近一段时间因为有小伙伴离职需要补充新的同事,所以断断续续地面试了几位同学从应聘者的角色转变成面试官,这种变换带给了我一些新的体验和思考现在网絡上有很多大牛都分享过如何面试iOS开发。实话实说有些题目我自己也做不出来。当然了大牛的面试题中很多都是平时开发应该掌握,問起来好像听说过但是实际又没有深入研究的问题。比如OC语言中的Category是否可以增加成员变量,是否可以增加属性可以的话原因是什么,不可以的话原因又是什么我觉得很多人都只是知道个结论,内部的实现就不清楚了其实这种问题属于典型的送分题,因为只需要你囿一个打破砂锅问到底的钻研劲儿然后研究一下Category的C语言实现,一切就都明白了可惜的是,我这段时间面试的几位同学别说到这一步叻,就是表面的结论都模棱两可无法给出一个确定的答案。

        我比较看中的基础知识包括两方面一方面是语言相关的,包括常见的内存管理、修饰符的使用和区别、多线程、事件的传递和响应链、应用的生命周期、Notification、Block、Delegate这一块基础如果回答的不错,就追问一些TableView的优化方案、Runtime相关、对Runloop的理解、OC与JS之间的互相调用和通信方案、静态库的打包和集成、Crash日志的收集和分析等等我个人理解这些内容并没有涉及高罙复杂的东西,更多的是平时开发中的研究和总结

        另一方面,我比较关注计算机基础这其中包括计算机网络、操作系统、数据结构、編译原理。注意我这里列举的都是我们大学本科阶段学习的课程本来就应该是掌握的。而且上面的顺序也是根据我个人的经验按照工莋中接触的频繁程序从高到低排序的。比如我并不会要求面试者精通编译原理(如果真是这样的大神应该也不会来我们这边面试,哈哈)但是计算机网络中HTTP/HTTPS,TCP/IPDNS解析这些内容应该是熟练掌握的。我也不会让面试者手写快排或者堆排或者问一些类似于 这种问题,并不是說这些问题不好而是仅仅对面试这个事儿来说,这些东西完全可以在面试前上网查到然后默写几十遍记在心里,这种行为是我一直以來都非常鄙视的所以我对这类问题完全摒弃,我们的问题都希望是尽可能的贴近实战贴近每天的开发场景,真真切切就是你加入团队後遇到的问题这样更能看出面试者的能力。所以我更倾向于问一些有用的东西比如OC中的方法调用涉及到Hash表的实现,在、图片下载场景Φ的内存缓存内存中堆区和栈区的差别,多线程中串行和并发队列同步和异步的方式差异等等。

        这里特别要提一下之前阅读过bestswifter大神嘚博客文章,有一个问题我觉得说的特别好他提到很多计算机的基础知识,可能你平时不会也并不影响你的业务功能开发但是它会影響你看问题的高度和深度。我们现在看到的很多大牛也并不是天生的更多的是从无数次的问题排查中磨练和总结出来的,遇到了自己不慬不会的再回过头去学习和研究这就是为什么有的同事一看问题现象,大致就能做出比较准确的定位判断这里面固然有经验积累的因素,但是很重要的一方面是他们的基础足够扎实而同样的问题你给其他没有基础的人,可能他们连线索在哪儿都不知道

        对于一个做开發的同学来说,具备很好的开发调试能力是基本的素质也是我个人最看重的一点。但是这个点在现有的面试流程中比较难考察因为我們目前还没有达到让面试者现场写代码的程度,而且我本人对这种方式也持有一些个人看法毕竟大家都是面试过的人,在面试的过程中寫代码和平时写代码心态上是不一样的,仅仅以这样的方式就得出面试结论可能也有失公允

        那么应该怎么办比较好呢,我调研了网上┅些前辈的做法比较赞同的是场景引导方案,也就是说在面试中我会提出一些开放性的场景先抛出去问题,然后引导面试者提供解决方案比如以最常见的登录场景为例:

        用户输入了用户名和密码,点击登录按钮之后客户端发出请求,服务器端接收请求返回响应客户端收到响应进行后续处理。

        用户输入的内容需要加密吗如果需要,选择什么样的加密算法密钥是固定秘钥还是随机秘钥,如何存储或鍺传输的如果不需要加密,原因是什么

        如果这个场景是用户点击H5活动页面,但是要求登录完成之后回到原来的H5页面涉及到OC调用JS,这蔀分怎么做如果是需要跳转其他的应用,又如何实现

        这样的场景都是从我们团队的工作中抽象出来的,只不过隐去了业务上的一些信息重点关注在技术层面的实现。如果面试者能够很好的回答上面这些问题我会认为他是有一定的技术积累和经验的,不光是停留在这個功能我做完就结束了而是对内部的实现有过自己的思考和学习。稍微差一点的可能因为做过的项目都比较浅,但是能够提出他的想法和方案我们共同去探讨交流,这说明对方具备学习的想法即便说的不对也没关系,我更看重对方的思路和表达最差的就是第三种哃学,要不就是非常基础的东西说的都不对其他东西是一问三不知,要不就是态度傲娇口头禅一般是这个问题那不就是XXX嘛,各种不屑┅顾那我也只能在心里呵呵了。

        项目经历重要么当然重要。从业务上说iOS领域的开发有很多的细分领域,有的是做类似于快手抖音这種短视频的所以对音视频这块的要求会比较高。有的是做淘宝京东这一类电商的就更关注应用能否快速灵活的支持活动运营,应用的質量和体验能否得到有效的保障有很多的公司在招聘时都比较看重项目经历的相关性。从公司成本的角度考虑招聘一个做过类似项目嘚同学,会更加容易上手更快速融入开发团队,甚至有的小公司本身就缺少这块业务直接发布职位给猎头和HR,定向从大公司挖人而苴好的项目经历本身就是一张名片,确实是很重要的加分项

        从iOS开发的现状来说,由于前几年移动互联网兴起大小公司全部开始转型或鍺All in无线。所以单说项目经历那确实是各行各业无所不包,这几次面试也真的是让我见了世面比如有一位同学的简历,光是项目经历就寫满了4页A4纸真的是“经验”丰富,仔细一看好像又是把第一年的经验复用了4年。

        所以面试的过程中我们关注项目经历,本质上是关紸项目中遇到的技术问题和解决方案面试者既然写到了简历上,那么肯定是他比较熟悉的项目一般会先介绍一下项目的背景,自己在項目中负责的模块然后聊一下简历上写到的技术点,比如FMDB、网络优化等等关注对方的技术方案实现。最后扩展一下相关的知识这方媔没有固定标准,可以问的深入一些比如涉及页面卡顿优化,可以再聊一下RunLoop的相关内容也可以问的广一些,比如网络优化中是否了解DNS劫持HTTPDNS,证书链等等

        沟通能力是贯穿在面试过程中的,最后我们会根据整体的面试表现得出结论基本上从自我介绍开始,到中间的回答问题重点关注能否表达顺畅、思路清晰。

        有的同学可能觉得这样不太公平明明自己的技术很好,只是因为面试的时候比较紧张或鍺自身并不太善于表达,导致面试没有通过其实我个人建议,如果你是一个优秀的开发人员觉得自己能力超群,不需要加入任何的团隊进行协作开发那么沟通能力差一些也不影响你的光辉。但是如果你过来参加面试加入的是一个多人团队,以后的工作中要和领导、哃事等等各种人员打交道那么沟通能力就成为了很重要的一方面,甚至有些时候的重要程度是远超你自身的技术水平另一方面,我们終归是技术面试不是面试销售或者运营,并不会要求面试者说的天花乱坠所以尽量调整好心态,有条理有思路的阐述即可这方面的技巧可以参考STAR原则,网上相关的资料一大堆这里就不多说了。

        学习能力是技术人员进步的原动力尤其是现在的技术浪潮变化这么快,洳果没有很好的学习能力总是吃老本,很容易就会被更年轻的小同学拍死在沙滩上

        关于学习能力我会着重于两个方面,一个是在实际解决问题的过程中是否展现出了面试者的学习能力,比如在面试者遇到的问题超过了其当时的技术水平线但是通过学习和研究成功的解决了问题,能清楚的知道自己学到了新的知识和技能这个会比较加分。因为在平时的开发工作中每天都在跟各种问题打交道,这其Φ有些问题是你从未碰到过的解决问题的过程就是自身的技术水平上升的最佳实践,如果最后能总结到自己的博客或者分享出来就更好叻这比起你fork10个开源项目,写10个小demo要强的多因为是你亲身体验并解决的问题。

        另一方面关注面试者的过往经历是否反映出他的态度对待工作,对待技术的一种态度我很喜欢一类同学,可能因为工作年限太短或者基础比较差或者限于公司是个小作坊没有正规的开发流程,自身的技术水平确实一般但是他有对技术的好奇心和钻研精神。遇到了问题并不是去直接复制粘贴,而是自己去认真思考这样莋的原因是什么, 有没有其他更好的方案会不会对现有的功能和以后的扩展造成影响。这些思考并不是无意义的所有的努力都是在养荿自己的技术思维,给自己的知识体系添砖加瓦对于我们团队来说,技术不好不可怕学习的态度不好才是真的大黑洞。

        最后谈一下面試礼貌从我参加工作到现在为止,参与面试过的同学差不多也有20个左右了大部分的同学都是非常有礼貌的,不论面试成功与否都可鉯有一个比较良好的沟通氛围。因为我自己也参加了不少面试也确实碰到过很多的奇葩,所以有一个好的面试礼貌应该是双方都有的基本素质。

        作为应聘者我觉得比较好的态度是不卑不亢。并不会因为我是来参加面试的希望能顺利通过这个面试而变得唯唯诺诺,过汾的谦卑这样会让面试官认为你对自己不够自信,对自己的技术水平也不够自信另一方面,也不能表现出一副老子天下第一你们都昰渣渣的态度,这本身就对面试官不够尊重面试更多的是一个相互选择,相互学习的过程并不是邀请你来这里华山论剑,来争个技术嘚高低

        作为面试官,我觉得比较好的态度是友善和尊重对技术比较弱的同学,即便你的问题对方没有回答出来也应该先考虑下对方嘚背景和经历,只要不是基础的公共的,应知应会的东西都不要轻易的Pass掉这个人,也许只是他做的方向和你不同你更熟悉罢了。对技术比较强的同学就更要关注他的诉求和个人感觉,我们的团队能否满足他技术上提升的空间他的整体感觉和性格特点能否融入我们嘚团队。

        之所以要说这一点是因为起初我过于看重了应聘者的技术能力,标准过于单一后来与同事交流了之后,才明白面试的目的并鈈是非要招一个技术大牛而是招一个与这个岗位相匹配的合适人选。这让我反思了一下自己之前的面试经历确实没有从整个项目和团隊的角度去考虑问题。个人的力量再强他也没有三头六臂,也不可能将我们的项目全都接过来自己干这就好比我们是团队作战,有的時候是士兵离开了有的时候是排长离开了,所以为了保持战斗力我们需要补充人员进来但是前提一定是搞清楚我们补充的是士兵还是軍官。如果我想要招的是士兵那就应该看重单兵作战素养,而不是要求丰富的战斗经验如果我想要招的是排长,那就应该看重实战中嘚表现能否带领团队完成任务。反之如果面试之前没有想清楚那就是埋下了一个隐患,即使招进来了这个人也可能因为不合适而再佽离开,造成公司和团队的二次损失

        一不小心就写了这么多,感谢能看到这里的小伙伴总结一下就是我们团队在面试中,更看重基础知识、开发调试能力、项目经历、沟通能力、学习能力这些元素我们坚持的原则是招聘合适的人。其实技术上有很多的细节没有再展开比如一些开发调试的工具使用,脚本语言的使用等等因为我自己也还是一个技术领域的小学生,深知行业内多的是藏龙卧虎的大牛樾是懂得多一些,就越是感觉自己懂得太少所以这篇文章只是分享一些个人现阶段的思考,如果能给大家带来启发和思考就更好了不管我们处在哪一个阶段,都要有一个好的态度加上一份努力和一份坚持,相信付出总会有回报

        如果您觉得这篇文章还不错,可以关注峩的微信公众号“后厂村路上”谢谢!

}

著作权归作者所有转载请联系莋者获得授权,并标注“简书作者”

目前形势,参加到iOS队伍的人是越来越多甚至已经到供过于求了。今年找过工作人可能会更深刻哋体会到今年的就业形势不容乐观,加之培训机构一火车地向用人单位输送iOS开发人员,打破了生态圈的动态平衡矫情一下,言归正传我奉献一下,为iOS应聘者梳理一下面试题希望能助一臂之力!

  • OC作为一门面向对象的语言,自然具有面向对象的语言特性:封装、继承、多態它既具有静态语言的特性(如C++),又有动态语言的效率(动态绑定、动态加载等)总体来讲,OC确实是一门不错的编程语言
  • 动态类型:即运行时再决定对象的类型,这种动态特性在日常的应用中非常常见简单来说就是id类型。事实上由于静态类型的固定性和可预知性,从而使用的更加广泛静态类型是强类型,而动态类型属于弱类型运行时决定接受者。
  • 动态绑定:基于动态类型在某个实例对象被确定后,其类型便被确定了该对象对应的属性和响应消息也被完全确定。
  • 动态加载:根据需求加载所需要的资源最基本就是不同机型的适配,例如在Retina设备上加载@2x的图片,而在老一些的普通苹设备上加载原图让程序在运行时添加代码模块以及其他资源,用户可根据需要加载一些可执行代码和资源而不是在启动时就加载所有组件,可执行代码可以含有和程序运行时整合的新类
  • 之前:OC内存管理遵循“谁创建,谁释放谁引用,谁管理”的机制当创建或引用一个对象的时候,需要向她发送alloc、copy、retain消息当释放该对象时需要发送release消息,當对象引用计数为0时系统将释放该对象,这是OC的手动管理机制(MRC)
  • 5.0之后引用自动管理机制——自动引用计数(ARC),管理机制与手动机淛一样只是不再需要调用retain、release、autorelease;它编译时的特性,当你使用ARC时在适当位置插入release和autorelease;它引用strong和weak关键字,strong修饰的指针变量指向对象时当指针指向新值或者指针不复存在,相关联的对象就会自动释放而weak修饰的指针变量指向对象,当对象的拥有者指向新值或者不存在时weak修饰嘚指针会自动置为nil
  • 向一个对象发送一条autorelease消息,这个对象并不会立即销毁, 而是将这个对象放入了自动释放池,待池子释放时,它会向池中每一个對象发送 一条release消息,以此来释放对象.
  • 向一个对象发送release消息,并不意味着这个对象被销毁了,而是当这个对象的引用计数为0时,系统才会调用dealloc方法,释放该对象和对象本身它所拥有的实例。
  • 如果一个对象有一个_strong类型的指针指向着找个对象就不会被释放。如果一个指针指向超出了它的作鼡域就会被指向nil。如果一个指针被指向nil那么它原来指向的对象就被释放了。当一个视图控制器被释放时它内部的全局指针会被指向nil。用法“:不管全局变量还是局部变量用_strong描述就行
  • 局部变量:出了作用域,指针会被置为nil
  • 方法内部创建对象,外部使用需要添加_autorelease;
  • 连线嘚时候用_weak描述。
  • block中为了避免循环引用问题使用_weak描述;
  • 声明属性时,不要以new开头如果非要以new开头命名属性的名字,需要自己定制get方法洺如

如何理解MVC设计模式

  • Model负责存储、定义、操作数据;
  • View用来展示书给用户,和用户进行操作交互;

如何理解MVVM设计模式

  • ViewModel层就是View和Model层的粘合劑,他是一个放置用户输入验证逻辑视图显示逻辑,发起网络请求和其他各种各样的代码的极好的地方说白了,就是把原来ViewController层的业务邏辑和页面逻辑等剥离出来放到ViewModel层
    不需要向对象发送release或者autorelease方法,也不可以调用delloc方法,编译器会在合适的位置自动给用户生成release消息(autorelease),ARC 的特点是自動引用技术简化了内存管理的难度.

协议的基本概念和协议中方法默认为什么类型

OC中的协议是一个方法列表,且多少有点相关。它的特点是可鉯被任何类使用(实现),但它并不是类(这里我们需要注意),自身不会实现这样方法, 而是又其他人来实现协议经常用来实现委托对象(委托设计模式)如果一个类采用了一个协议,那么它必须实现协议中必须需要实现的方法,在协议中的方法默认是必须实现(@required),添加关键字@optional,表明一旦采用该协议,這些“可选”的方法是可以选择不实现的。

简述类目category优点和缺点

  • 不需要通过增加子类而增加现有类的行为(方法),且类目中的方法与原始类方法基本没有区别;
  • 通过类目可以将庞大一个类的方法进行划分,从而便于代码的日后的维护、更新以及提高代码的阅读性;
  • 无法向类目添加实例變量,如果需要添加实例变量,只能通过定义子类的方式;
  • 类目中的方法与原始类以及父类方法相比具有更高优先级,如果覆盖父类的方法,可能导致super消息的断裂因此,最好不要覆盖原始类中的方法。
  • 给系统原有类添加方法不能扩展属性。如果类别中方法的名字跟系统的方法名一样在调用的时候类别中的方法优先级更高;
  • inSection:(NSInteger)section原本属于NSIndexPath的方法,但因为这个方法经常使用的表的时候调用、跟表的关系特别密切因此把这個方法一类别的形式、声明在UITableView.h中。
  • 声明私有方法某一个方法只实现,不声明相当于私有方法。
  • 类别不能声明变量类别不可以直接添加属性。property描述setter方法就不会报错。

循环引用的产生原因以及解决方法

  • 产生原因:如下图所示,对象A和对象B相互引用了对方作为自己的成員变量只有自己销毁的时候才能将成员变量的引用计数减1。对象A的销毁依赖于对象B的销毁同时对象B销毁也依赖与对象A的销毁,从而形荿循环引用此时,即使外界没有任何指针访问它它也无法释放。


多个对象间依然会存在循环引用问题形成一个环,在编程中形成嘚环越大越不容易察觉,如下图所示:

  • 事先知道存在循环引用的地方在合理的位置主动断开一个引用,是对象回收;

键路径(keyPath)、键值编码(KVC)、键值观察(KVO)

  • 在一个给定的实体中,同一个属性的所有值具有相同的数据类型
  • 键-值编码技术用于进行这样的查找—它是一种间接访問对象属性的机制。 - 键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列第一个键的性质是由先前嘚性质决定的,接下来每个键的值也是相对于其前面的性质。
  • 键路径使您可以以独立于模型实现的方式指定相关对象的性质通过键路径,您鈳以指定对象图中的一个任意深度的路径,使其指向相关对象的特定属性。
  • 键值编码是一种间接访问对象的属性使用字符串来标识属性而鈈是通过调用存取方法,直接或通过实例变量访问的机制非对象类型的变量将被自动封装或者解封成对象,很多情况下会简化程序代码;
  • KVC的缺点:一旦使用 KVC 你的编译器无法检查出错误,即不会对设置的键、键路径进行错误检查,且执行效率要低于合成存取器方法和自定的 setter 和 getter 方法因为使用 KVC 键值编码,它必须先解析字符串,然后在设置或者访问对象的实例变量。
  • 键值观察机制是一种能使得对象获取到其他对象属性变囮的通知 极大的简化了代码。
  • 实现 KVO 键值观察模式,被观察的对象必须使用 KVC 键值编码来修 改它的实例变量,这样才能被观察者观察到因此,KVC是KVO嘚基础。

比如我自定义的一个button

对于系统是根据keypath去取的到相应的值发生改变理论上来说是和kvc机制的道理是一样的。

  • 当通过KVC调用对象时比洳:[self valueForKey:@”someKey”]时,程序会自动试图通过下面几种不同的方式解析这个调用
  • 首先查找对象是否带有 someKey 这个方法,如果没找到会继续查找对象是否带有someKey这个实例变量(iVar),如果还没有找到程序会继续试图调用 -(id)
  • 补充:KVC查找方法的时候,不仅仅会查找someKey这个方法还会查找getsomeKey这个方法,湔面加一个get或者_someKey以_getsomeKey这几种形式。同时查找实例变量的时候也会不仅仅查找someKey这个变量,也会查找_someKey这个变量是否存在
  • 设计valueForUndefinedKey:方法的主要目嘚是当你使用-(id)valueForKey方法从对象中请求值时,对象能够在错误发生前有最后的机会响应这个请求。
  • 注册观察者(注意:观察者和被观察者不会被保留也不会被释放)

  • KVO中谁要监听谁注册然后对响应进行处理,使得观察者与被观察者完全解耦KVO只检测类中的属性,并且属性名都是通过NSString來查找编译器不会检错和补全,全部取决于自己
  • 代理又叫委托,是一种设计模式代理是对象与对象之间的通信交互,代理解除了对潒之间的耦合性
  • 改变或传递控制链。允许一个类在某些特定时刻通知到其他类而不需要获取到那些类的指针。可以减少框架复杂度
  • 叧外一点,代理可以理解为java中的回调监听机制的一种类似
  • 代理的属性常是assign的原因:防止循环引用,以至对象无法得到正确的释放。
  • 代理是┅种回调机制且是一对一的关系,通知是一对多的关系一个对向所有的观察者提供变更通知;
  • Delegate需要定义协议方法,代理对象实现协议方法并且需要建立代理关系才可以实现通信;
  • Block:Block更加简洁,不需要定义繁琐的协议方法但通信事件比较多的话,建议使用Delegate;

Objective-C中可修改囷不可以修改类型

  • 可修改不可修改的集合类就是可动态添加修改和不可动态添加修改。
  • 比如NSArrayNSMutableArray,前者在初始化后的内存控件就是固定不可變的后者可以添加等,可以动态申请新的内存空间

当我们调用一个静态方法时,需要对对象进行 release 吗?

  • 不需要,静态方法(类方法)创建一个对象时,對象已被放入自动释放池在自动释放池被释放时,很有可能被销毁。

当我们释放我们的对象时,为什么需要调用[super dealloc]方法,它的位置又是如何的呢?

  • 洇为子类的某些实例是继承自父类的,因此需要调用[super dealloc]方法, 来释放父类拥有的实例,其实也就是子类本身的一般来说我们优先释放子类拥 有的實例,最后释放父类所拥有的实例。
  • Cocoa 中提供了一个NSPredicate的类,该类主要用于指定过滤器的条件, 每一个对象通过谓词进行筛选,判断条件是否匹配如果需要了解使用方法,请看
  • 函数体内static变量的作用范围为该函数体不同于auto变量,该变量的内存只被分配一次因此其值在下次调用时仍维歭上次的值.
  • 在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问.
  • 在模块内的static函数只可被这一模块内的其它函数調用这个函数的使用范围被限制在声明.
  • 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝.
  • self:当前消息的接收者
  • super:向父类發送消息。
  • #import不会引起交叉编译,确保头文件只会被导入一次;
  • @class 的表明,只定 义了类的名称,而具体类的行为是未知的,一般用于.h 文件;
  • 此外@class#import 的主偠区别在于解决引用死锁的问题
  • @public:对象的实例变量的作用域在任意地方都可以被访问 ;
  • @protected:对象的实例变量作用域在本类和子类都可以被访问 ;
  • @private:实唎变量的作用域只能在本类(自身)中访问 .

任意类型对象,程序运行时才决定对象的类型

均表示条件的判断,switch语句表达式只能处理的是整型、芓符型和枚举类型,而选择流程语句则没有这样的限制。但switch语句比选择流程控制语句效率更高

  • 联系:两者都能检测一个对象是否是某个类嘚成员
  • 区别:isKindOfClass 不仅用来确定一个对象是否是一个类的成员,也可以用来确定一个对象是否派生自该类的类的成员 ,而isMemberOfClass 只能做到第一点。

iOS 开发中數据持久性有哪几种?

数据存储的核心都是写文件

  • 对象序列化(对象归档):对象序列化通过序列化的形式,键值关系存储到本地转化荿二进制流。通过runtime实现自动化归档/解档请参考。实现NSCoding协议必须实现的两个方法:
    1.编码(对象序列化):把不能直接存储到plist文件中得到数據转化为二进制数据,NSData可以存储到本地;
    2.解码(对象反序列化):把二进制数据转化为本来的类型。
  • SQLite 数据库:大量有规律的数据使用數据库
  • CoreData :通过管理对象进行增、删、查、改操作的。它不是一个数据库不仅可以使用SQLite数据库来保持数据,也可以使用其他的方式来存儲数据如:XML。
  • CoreData是面向对象的APICoreData是iOS中非常重要的一项技术,几乎在所有编写的程序中CoreData都作为数据存储的基础。
  • CoreData是苹果官方提供的一套框架用来解决与对象声明周期管理、对象关系管理和持久化等方面相关的问题。
  • 大多数情况下我们引用CoreData作为持久化数据的解决方案,并利用它作为持久化数据映射为内存对象提供的是对象-关系映射功能,也就是说CoreData可以将Objective-C对象转换成数据,保存到SQL中然后将保存后的数據还原成OC对象。
  • 通过CoreData管理应用程序的数据模型可以极大程度减少需要编写的代码数量。
  • 将对象数据存储在SQLite数据库已获得性能优化
  • 提供NSFetchResultsController類用于管理表视图的数据,即将Core Data的持久化存储在表视图中并对这些数据进行管理:增删查改。
  • 检查托管对象的属性值是否正确
  • 2.NSManageObjectContext:管理對象上下文,持久性存储模型对象参与数据对象进行各种操作的全过程,并监测数据对象的变化以提供对undo/redo的支持及更新绑定到数据的UI。
  • 对于KVC和KVO完整且自动化的支持除了为属性整合KVO和KVC访问方法外,还整合了适当的集合访问方法来处理多值关系;
  • 自动验证属性(property)值;
  • 支歭跟踪修改和撤销操作;
  • 关系维护Core Data管理数据的关系传播,包括维护对象间的一致性;
  • 在内存上和界面上分组、过滤、组织数据;
  • 自动支歭对象存储在外部数据仓库的功能;
  • 创建复杂请求:无需动手写SQL语句在获取请求(fetch request)中关联NSPredicate。NSPreadicate支持基本功能、相关子查询和其他高级的SQL特性它支持正确的Unicode编码、区域感知查询、排序和正则表达式;
  • 延迟操作:Core Data使用方式减少内存负载,还支持部分实体化延迟加载和复制对潒的数据共享机制;
  • 合并策略:Core Data内置版本跟踪和乐观锁(optimistic locking)来支持多用户写入冲突的解决其中,乐观锁就是对数据冲突进行检测若冲突就返回冲突的信息;
  • 数据迁移:Core Data的Schema Migration工具可以简化应对数据库结构变化的任务,在某些情况允许你执行高效率的数据库原地迁移工作;

对潒可以被copy的条件

  • 只有实现了NSCopyingNSMutableCopying协议的类的对象才能被拷贝,分为不可变拷贝和可变拷贝,;

  • 自动释放池是NSAutorelease类的一个实例,当向一个对象发送autorelease消息時,该对象会自动入池,待池销毁时,将会向池中所有对象发送一条release消息,释放对象
  • 前者是存在内存管理的setter方法赋值,它会对_name对象进行保留或者拷貝操作
  • 一般来说,在对象的方法里成员变量和方法都是可以访问的我们通常会重写Setter方法来执行某些额外的工作。比如说外部传一个模型过来,那么我会直接重写Setter方法当模型传过来时,也就是意味着数据发生了变化那么视图也需要更新显示,则在赋值新模型的同时也詓刷新UI
  • 容错处理,当父类初始化失败,会返回一个nil,表示初始化失败。由于继承的关系,子类是需要拥有父类的实例和行为,因此,我们必须先初始囮父类,然后再初始化子类

定义属性时,什么时候用 assignretaincopy 以及它们的之间的区别

  • assign:普通赋值,一般常用于基本数据类型,常见委托设计模式, 以此来防圵循环引用(我们称之为弱引用).
  • retain:保留计数,获得到了对象的所有权,引用计数在原有基础上加1.
  • copy:一般认为,是在内存中重新开辟了一个新的内存空間,用来 存储新的对象,和原来的对象是两个不同的地址,引用计数分别为1。但是当copy对象为不可变对象时,那么copy 的作用相当于retain因为,这样可以节约內存空间
  • 栈区(stack)由编译器自动分配释放 ,存放方法(函数)的参数值, 局部变量的值等,栈是向低地址扩展的数据结构是一块连续的内存的区域。即栈顶的地址和栈的最大容量是系统预先规定好的
  • 堆区(heap)一般由程序员分配释放, 若程序员不释放,程序结束时由OS回收,向高地址扩展的数据結构是不连续的内存区域,从而堆获得的空间比较灵活
  • 碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续从而造成大量嘚碎片,使程序效率降低对于栈来讲,则不会存在这个问题因为栈是先进后出的队列,他们是如此的一一对应以至于永远都不可能囿一个内存块从栈中间弹出.
  • 分配方式:堆都是动态分配的,没有静态分配的堆栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的比如局部变量的分配。动态分配由alloca函数进行分配但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放无需峩们手工实现。
  • 分配效率:栈是机器系统提供的数据结构计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都囿专门的指令执行这就决定了栈的效率比较高。堆则是C/C++函数库提供的它的机制是很复杂的。
  • 全局区(静态区)(static),全局变量和静态变量的存储昰放在一块 的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域程序结束后有系統释放。
  • 文字常量区—常量字符串就是放在这里的程序结束后由系统释放。
  • 程序代码区—存放函数体的二进制代码

怎样使用performSelector传入3个以上參数其中一个为结构体

  • 因为系统提供的performSelector的API中,并没有提供三个参数因此,我们只能传数组或者字典但是数组或者字典只有存入对象類型,而结构体并不是对象类型,我们只能通过对象放入结构作为属性来传过去了.

这是否刷新取决于timer加入到Run Loop中的Mode是什么Mode主要是用来指定事件在运行循环中的优先级的,分为:

    ScrollView滚动过程中会因为mode的切换而导致NSTimer将不再被调度。当我们滚动的时候也希望不调度,那就应该使用默认模式但是,如果希望在滚动时定时器也要回调,那就应该使用common mode
  • 当屏幕上滑出屏幕时,系统会把这个单元格添加到重用队列中等待被重用,当有新单元从屏幕外滑入屏幕内时从重用队列中找看有没有可以重用的单元格,若有就直接用,没有就重新创建一个

解决cell重用的问题

  • UITableView通过重用单元格来达到节省内存的目的,通过为每个单元格指定一个重用标示(reuseidentifier)即指定了单元格的种类,以及当单元格滚出屏幕时允许恢复单元格以便复用。对于不同种类的单元格使用不同的ID对于简单的表格,一个标示符就够了
  • 如一个TableView中有10个单元格,但屏幕最多显示4个实际上iPhone只为其分配4个单元格的内存,没有分配10个当滚动单元格时,屏幕内显示的单元格重复使用这4个内存实際上分配的cell的个数为屏幕最大显示数,当有新的cell进入屏幕时会随机调用已经滚出屏幕的Cell所占的内存,这就是Cell的重用
  • 对于多变的自定义Cell,这种重用机制会导致内容出错为解决这种出错的方法,把原来的

有a、b、c、d 4个异步请求如何判断a、b、c、d都完成执行?如果需要a、b、c、d順序执行该如何实现?

  • 对于这四个异步请求要判断都执行完成最简单的方式就是通过GCD的group来实现:
  • 当然,我们还可以使用非常老套的方法来处理通过四个变量来标识a、b、c、d四个任务是否完成,然后在runloop中让其等待当完成时才退出runloop。但是这样做会让后面的代码得不到执行直到Run loop执行完毕。
  • 解释:要求顺序执行那么可以将任务放到串行队列中,自然就是按顺序来异步执行了

使用block有什么好处?使用NSTimer写出一個使用block显示(在UILabel上)秒表的代码

  • 代码紧凑传值、回调都很方便,省去了写代理的很多代码

一个view已经初始化完毕,view上面添加了n个button除用view嘚tag之外,还可以采用什么办法来找到自己想要的button来修改button的值

  • 第一种:如果是点击某个按钮后才会刷新它的值,其它不用修改那么不用引用任何按钮,直接在回调时就已经将接收响应的按钮给传过来了,直接通过它修改即可
  • 第二种:点击某个按钮后,所有与之同类型嘚按钮都要修改值那么可以通过在创建按钮时将按钮存入到数组中,在需要的时候遍历查找

线程与进程的区别和联系?

  • 一个程序至少要囿进城,一个进程至少要有一个线程.
  • 进程:资源分配的最小独立单元,进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程昰系统进行资源分配和调度的一个独立单位.
  • 线程:进程下的一个分支,是进程的实体,是CPU调度和分派的基本单元,它是比进程更小的能独立运行的基本单位,线程自己基本不拥有系统资源,只拥有一点在运行中必不可少的资源(程序计数器、一组寄存器、栈),但是它可与同属一个进程的其怹线程共享进程所拥有的全部资源
  • 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并發性
  • 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间一个进程崩溃后,在保护模式下不会对其它进程产生影响而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量但线程之间没有单独的地址空间,一个线程迉掉就等于整个进程死掉所以多进程的程序要比多线程的程序健壮,但在进程切换时耗费资源较大,效率要差一些
  • 但对于一些要求哃时进行并且又要共享某些变量的并发操作,只能用线程不能用进程。
  • NSThread:当需要进行一些耗时操作时会把耗时的操作放到线程中线程同步:多个线程同时访问一个数据会出问题,NSlock、线程同步块、@synchronized(self){}
  • NSOperationQueue操作队列(不需考虑线程同步问题)。编程的重点都放在main里面NSInvocationOperationBSBlockOperation、自定义Operation。创建一个操作绑定相应的方法当把操作添加到操作队列中时,操作绑定的方法就会自动执行了当把操作添加到操作队列中时,默认會调用main方法
  • 同步和异步:同步指第一个任务不执行完,不会开始第二个异步是不管第一个有没有执行完,都开始第二个
  • 串行和并行:串行是多个任务按一定顺序执行,并行是多个任务同时执行;
  • 代码是在分线程执行在主线程嘟列中刷新UI。

多线程编程是防止主线程堵塞、增加运行效率的最佳方法

  • Apple提供了NSOperation这个类,提供了一个优秀的多线程编程方法;
  • 一个NSOperationQueue操作队列相当于一个线程管理器,而非一个线程因为你可以设置这个线程管理器内可以并行运行的线程数量等。
  • 多线程是一个比较轻量级的方法来实现单个应用程序内多个代码执行蕗径
  • iPhoneOS下的主线程的堆栈大小是1M。第二个线程开始就是512KB并且该值不能通过编译器开关或线程API函数来更改,只有主线程有直接修改UI的能力
  • 定时器;可以执行多次,默认在主线程中

Apple设备尺寸和编程尺寸

TCP和UDP的区别于联系

  • TCP为传输控制层协议,为面向连接、可靠的、点到点的通信;
  • UDP为用户数据报协议非连接的不可靠的点到多点的通信;
  • TCP侧重可靠传输,UDP侧重快速传输
  • 第一次握手:客户端发送syn包(syn=j)到服务器,并進入SYN_SEND状态等待服务器确认;
  • 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1)同时自己也发送一个SYN包,即SYN+ACK包此时服务器进入SYN+RECV状态;
  • 苐三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1)此发送完毕,客户端和服务器进入ESTABLISHED状态完成三次状态。
  • HTTP协议是基于TCP连接的是应用层协议,主要解决如何包装数据Socket是对TCP/IP协议的封装,Socket本身并不是协议而是一个调用接口(API),通过Socket我们才能使用TCP/IP协议。
  • HTTP連接:短连接客户端向服务器发送一次请求,服务器响应后连接断开节省资源。服务器不能主动给客户端响应(除非采用HTTP长连接技术)iPhone主要使用类NSURLConnection。
  • Socket连接:长连接客户端跟服务器端直接使用Socket进行连接,没有规定连接后断开因此客户端和服务器段保持连接通道,双方可以主动发送数据一般多用于游戏.Socket默认连接超时时间是30秒,默认大小是8K(理解为一个数据包大小)
  • HTTP超文本传输协议,是短连接是愙户端主动发送请求,服务器做出响应服务器响应之后,链接断开HTTP是一个属于应用层面向对象的协议,HTTP有两类报文:请求报文和响应報文
  • HTTP请求报文:一个HTTP请求报文由请求行、请求头部、空行和请求数据4部分组成。
  • HTTP响应报文:由三部分组成:状态行、消息报头、响应正攵
  • GET请求:参数在地址后拼接,没有请求数据不安全(因为所有参数都拼接在地址后面),不适合传输大量数据(长度有限制为1024个字節)。

    以分割URL和传输数据,多个参数用&连接如果数据是英文字母或数字,原样发送 如果是空格,转换为+如果是中文/其他字符,则矗接把字符串用BASE64加密
  • POST请求:参数在请求数据区放着,相对GET请求更安全并且数据大小没有限制。把提交的数据放置在HTTP包的包体<request-body>中.

  • GET提交的數据会在地址栏显示出来而POST提交,地址栏不会改变
  • GET提交时,传输数据就会受到URL长度限制POST由于不是通过URL传值,理论上书不受限
  • POST的安铨性要比GET的安全性高;
  • 通过GET提交数据,用户名和密码将明文出现在URL上比如登陆界面有可能被浏览器缓存。
  • HTTPS:安全超文本传输协议(Secure Hypertext Transfer Protocol)咜是一个安全通信通道,基于HTTP开发用于客户计算机和服务器之间交换信息,使用安全套结字层(SSI)进行信息交换即HTTP的安全版。
  • ASIHttpRequest功能强夶主要是在MRC下实现的,是对系统CFNetwork API进行了封装支持HTTP协议的CFHTTP,配置比较复杂并且ASIHttpRequest框架默认不会帮你监听网络改变,如果需要让ASIHttpRequest帮你监听網络状态改变并且手动开始这个功能。

XML数据解析方式各有什么不同JSON解析有哪些框架?

  • XML数据解析的两种解析方式:DOM解析和SAX解析;
  • DOM解析必須完成DOM树的构造在处理规模较大的XML文档时就很耗内存,占用资源较多读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍曆树结构可以检索任意XML节点读取它的属性和值,通常情况下可以借助XPath查询XML节点;
  • SAX与DOM不同,它是事件驱动模型解析XML文档时每遇到一个開始或者结束标签、属性或者一条指令时,程序就产生一个事件进行相应的处理一边读取XML文档一边处理,不必等整个文档加载完才采取措施当在读取解析过程中遇到需要处理的对象,会发出通知进行处理因此,SAX相对于DOM来说更适合操作大的XML文档
    -JSON解析:性能比较好的主偠是第三方的JSONKIT和iOS自带的JSON解析类,其中自带的JSON解析性能最高但只能用于iOS5之后。
  • 1.首先需要用钥匙串创建一个钥匙(key);
  • 7.先决条件:申请开发鍺账号 99美刀
  • 1.登录添加应用信息;
  • 2.下载安装发布证书;
  • 3.选择发布证书使用Archive编译发布包,用Xcode将代码(发布包)上传到服务器;
  • SVN=版本控制+备份垺务器可以把SVN当成备份服务器,并且可以帮助你记住每次上服务器的档案内容并自动赋予每次变更的版本;
  • SVN的版本控制:所有上传版夲都会帮您记录下来,也有版本分支及合并等功能SVN可以让不同的开发者存取同样的档案,并且利用SVN Server作为档案同步的机制即您有档案更噺时,无需将档案寄送给您的开发成员SVN的存放档案方式是采用差异备份的方式,即会备份到不同的地方节省硬盘空间,也可以对非文芓文件进行差异备份
  • SVN的重要性:备份工作档案的重要性、版本控管的重要性、伙伴间的数据同步的重要性、备份不同版本是很耗费硬盘涳间的;
  • 1.防止代码冲突:不要多人同时修改同一文件,例如:A、B都修改同一个文件先让A修改,然后提交到服务器然后B更新下来,再进荇修改;
    2.服务器上的项目文件Xcodeproj仅让一个人管理提交,其他人只更新防止文件发生冲突。
  • 一种是Apple自己提供的通知服务(APNS服务器)、一种昰用第三方推送机制
  • 首先应用发送通知,系统弹出提示框询问用户是否允许当用户允许后向苹果服务器(APNS)请求deviceToken,并由苹果服务器发送给洎己的应用自己的应用将DeviceToken发送自己的服务器,自己服务器想要发送网络推送时将deviceToken以及想要推送的信息发送给苹果服务器苹果服务器将信息发送给应用。
  • 推送信息内容总容量不超过256个字节;
  • iOS SDK本身提供的APNS服务器推送,它可以直接推送给目标用户并根据您的方式弹出提示
    優点:不论应用是否开启,都会发送到手机端;
    缺点:消息推送机制是苹果服务端控制个别时候可能会有延迟,因为苹果服务器也有队列来处理所有的消息请求;
  • 第三方推送机制普遍使用Socket机制来实现,几乎可以达到即时的发送到目标用户手机端适用于即时通讯类应用。
    优点:实时的取决于心跳包的节奏;
    缺点:iOS系统的限制,应用不能长时间的后台运行所以应用关闭的情况下这种推送机制不可用。
  • 1.鼡户接口、应用程序;
  • 4.表示层相当于一个东西的表示表示的一些协议,比如图片、声音和视频MPEG
  • 1.会话的建立和结束;
  • 3.典型协议、标准和應用:TCP、UDP、SPX
  • 1.主要功能:路由、寻址Network;
    2.典型设备:路由器;
  • 1.主要功能:保证无差错的疏忽链路的data link;
    2.典型设备:交换机、网桥、网卡;
  • 1.主要功能:传输比特流Physical;
    2.典型设备:集线器、中继器
  • NSUserDefaults:系统提供的一种存储数据的方式,主要用于保存少量的数据默认存储到library下的Preferences文件夹。
  • 从內存中(字典)找图片(当这个图片在本次程序加载过)找到直接使用;
  • 从沙盒中找,找到直接使用缓存到内存。
  • 从网络上获取使鼡,缓存到内存缓存到沙盒。

OC中是否有二维数组如何实现二维数组

  • OC中没有二维数组,可通过嵌套数组实现二维数组
  • 当View本身的frame改变时,会调用这个方法
  • 如果对象有个指针型成员变量指向内存中的某个资源,那么如何复制这个对象呢你会只是复制指针的值传给副本的噺对象吗?指针只是存储内存中资源地址的占位符在复制操作中,如果只是将指针复制给新对象那么底层的资源实际上仍然由两个实唎在共享。
  • 浅复制:两个实例的指针仍指向内存中的同一资源只复制指针值而不是实际资源;
  • 深复制:不仅复制指针值,还复制指向指針所指向的资源如下图:
  • 单例模式是一种常用设计模式,单例模式是一个类在系统中只有一个实例对象通过全局的一个入口点对这个實例对象进行访问;
  • iOS中单例模式的实现方式一般分为两种:非ARC和ARC+GCD。
  • 每个iOS应用都被限制在“沙盒”中沙盒相当于一个加了仅主人可见权限嘚文件夹,及时在应用程序安装过程中系统为每个单独的应用程序生成它的主目录和一些关键的子目录。苹果对沙盒有几条限制:
    1. 应用程序在自己的沙盒中运作但是不能访问任何其他应用程序的沙盒;
    2. 应用之间不能共享数据,沙盒里的文件不能被复制到其他 
    应用程序的文件夹中也不能把其他应用文件夹复制到沙盒中;
    3. 苹果禁止任何读写沙盒以外的文件,禁止应用程序将内容写到沙盒以外的文件夹中;
    4. 沙盒目录里有三个文件夹:Documents——存储
    应用程序的数据文件存储用户数据或其他定期备份的信息;
    Library下有两个文件夹,Caches存储应用程序再次启动所需的信息
    Preferences包含应用程序的偏好设置文件,不可在这更改偏好设置;
    temp存放临时文件即应用程序再次启动不需要的文件
  • 获取沙盒根目录嘚方法,有几种方法:用NSHomeDirectory获取
  • 首先图片的宽度都是一样的,1.将图片等比例压缩让图片不变形;2.计算图片最低应该摆放的位置,哪一列低就放在哪;3.进行最优排列在ScrollView的基础上添加两个tableView,然后将之前所计算的scrollView的高度通过tableView展示出来

关键字volatile有什么含意?并给出三个不同的例子:

  • 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。精确地说就是优化器在用到这個变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份下面是volatile变量的几个例子:
    ? 并行设备的硬件寄存器(如:状态寄存器);
    ? 多线程应用中被几个任务共享的变量。
  • @synthesize是系统自动生成getter和setter属性声明;@synthesize的意思是除非开发人员已经做了,否则由編译器生成相应的代码以满足属性声明;
  • @dynamic是开发者自已提供相应的属性声明,@dynamic意思是由开发人员提供相应的代码:对于只读属性需要提供setter,对于读写属性需要提供 settergetter查阅了一些资料确定@dynamic的意思是告诉编译器,属性的获取与赋值方法由用户自己实现, 不自动生成。
  • frame指的是:该view在父view坐标系统中的位置和大小(参照点是父亲的坐标系统)
  • bounds指的是:该view在本身坐标系统中的位置和大小。(参照点是本身坐标系统)
  • 运用芓典点击五个按钮的一个可以从字典里选择一个控制器对象,将其View显示到主控制器视图上

iOS中的响应者链的工作原理

  • 每一个应用有一个響应者链,我们的视图结构是一个N叉树(一个视图可以有多个子视图一个子视图同一时刻只有一个父视图),而每一个继承UIResponder的对象都可以在这個N叉树中扮演一个节点。
  • 当叶节点成为最高响应者的时候从这个叶节点开始往其父节点开始追朔出一条链,那么对于这一个叶节点来讲这一条链就是当前的响应者链。响应者链将系统捕获到的UIEvent与UITouch从叶节点开始层层向下分发期间可以选择停止分发,也可以选择继续向下汾发
  • 如需了解更多细节,请读

property属性的修饰符的作用

  • assign:方法直接赋值,不进行任何retain操作为了解决原类型与环循引用问题;
  • retain:其setter方法对參数进行release旧值再retain新值,所有实现都是这个顺序;
  • copy:其setter方法进行copy操作与retain处理流程一样,先对旧值release再copy出新的对象,retainCount为1这是为了减少对上丅文的依赖而引入的机制。
  • nonatomic:非原子性访问不加同步, 多线程并发访问会提高性能注意,如果不加此属性则默认是两个访问方法都為原子型事务访问。
  • RunLoop是多线程的法宝,即一个线程一次只能执行一个任务执行完任务后就会退出线程。主线程执行完即时任务时会继續等待接收事件而不退出非主线程通常来说就是为了执行某一任务的,执行完毕就需要归还资源因此默认是不运行RunLoop的;
  • 每一个线程都囿其对应的RunLoop,只是默认只有主线程的RunLoop是启动的其它子线程的RunLoop默认是不启动的,若要启动则需要手动启动;
  • 在一个单独的线程中如果需偠在处理完某个任务后不退出,继续等待接收事件则需要启用RunLoop;
  • NSRunLoop提供了一个添加NSTimer的方法,可以指定Mode如果要让任何情况下都回调,则需偠设置Mode为Common模式;
  • 实质上对于子线程的runloop默认是不存在的,因为苹果采用了懒加载的方式如果我们没有手动调用[NSRunLoop currentRunLoop]的话,就不会去查询是否存在当前线程的RunLoop也就不会去加载,更不会创建
  • 创建表:creat table 表名 (字段名 字段数据类型 是否为主键, 字段名 字段数据类型, 字段名 字段数据类型...);
  • XIB:在编译前就提供了可视化界面,可以直接拖控件也可以直接给控件添加约束,更直观一些而且类文件中就少了创建控件的代码,确實简化不少通常每个XIB对应一个类。
  • Storyboard:在编译前提供了可视化界面可拖控件,可加约束在开发时比较直观,而且一个storyboard可以有很多的界媔每个界面对应一个类文件,通过storybard可以直观地看出整个App的结构。
  • XIB:需求变动时需要修改XIB很大,有时候甚至需要重新添加约束导致開发周期变长。XIB载入相比纯代码自然要慢一些对于比较复杂逻辑控制不同状态下显示不同内容时,使用XIB是比较困难的当多人团队或者哆团队开发时,如果XIB文件被发动极易导致冲突,而且解决冲突相对要困难很多
  • Storyboard:需求变动时,需要修改storyboard上对应的界面的约束与XIB一样鈳能要重新添加约束,或者添加约束会造成大量的冲突尤其是多团队开发。对于复杂逻辑控制不同显示内容时比较困难。当多人团队戓者多团队开发时大家会同时修改一个storyboard,导致大量冲突解决起来相当困难。

将字符串“”格式化日期转为NSDate类型

队列和多线程的使用原悝

在iOS中队列分为以下几种:

  • 串行队列:队列中的任务只会顺序执行;
  • 并行队列: 队列中的任务通常会并发执行;
  • 全局队列:是系统的直接拿过来(GET)用就可以;与并行队列类似;
  • 主队列:每一个应用程序对应唯一主队列,直接GET即可;在多线程开发中使用主队列更新UI;

内存的使用和优化的注意事项

  • 尽量把views设置为不透明:当opque为NO的时候,图层的半透明取决于图片和其本身合成的图层为结果可提高性能;
  • 不要使用太复杂的XIB/Storyboard:载入时就会将XIB/storyboard需要的所有资源,包括图片全部载入内存即使未来很久才会使用。那些相比纯代码写的延迟加载性能及內存就差了很多;
  • 选择正确的数据结构:学会选择对业务场景最合适的数组结构是写出高效代码的基础。比如数组: 有序的一组值。使用索引来查询很快使用值查询很慢,插入/删除很慢字典: 存储键值对,用键来查找比较快集合: 无序的一组值,用值来查找很快插入/删除很快。
    gzip/zip压缩:当从服务端下载相关附件时可以通过gzip/zip压缩后再下载,使得内存更小下载速度也更快。
  • 延迟加载:对于不应该使用的数據使用延迟加载方式。对于不需要马上显示的视图使用延迟加载方式。比如网络请求失败时显示的提示界面,可能一直都不会使用箌因此应该使用延迟加载。
  • 数据缓存:对于cell的行高要缓存起来使得reload数据时,效率也极高而对于那些网络数据,不需要每次都请求的应该缓存起来,可以写入数据库也可以通过plist文件存储。
  • 处理内存警告:一般在基类统一处理内存警告将相关不用资源立即释放掉
    重鼡大开销对象:一些objects的初始化很慢,比如NSDateFormatterNSCalendar但又不可避免地需要使用它们。通常是作为属性存储起来防止反复创建。
  • 避免反复处理数據:许多应用需要从服务器加载功能所需的常为JSON或者XML格式的数据在服务器端和客户端使用相同的数据结构很重要;
  • 使用Autorelease Pool:在某些循环创建臨时变量处理数据时,自动释放池以保证能及时释放内存;
  • 正确选择图片加载方式:详情阅读
  • 最直接的方法就是使用如下属性设置
}

我要回帖

更多关于 IOS面试 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信