Objective-C 底层

  Objective-C runtime library:Objective-C 的对象模型,Block 的底层实现结构,消息发送,消息转发,category,method 实现,class load。

  runtime 我在平时很少涉及到,没有系统学习过,而且很多次看了不久就忘了,所以这里给出一些不错的文章的链接供参考。这几个问题在《iOS 7 Programming Pushing the Limits》都有过深入的解读(我有电子版,是盗版,这里给出这本书在 Github 的地址,工作后我会把去年看过的盗版书全部补偿买回,没有 iOS 8 的版本,不知道是不是由于盗版太多导致的)。另外,唐巧前辈撰文讨论过前两者:如果需要提高你的ios水平,可以参加ios培训,比较自学是有限的,

  1. 《Objective-C 对象模型及应用》

  唐巧在后记中也提到了 iOS 64-bit 带来的变化:

  那么就来看看 Session 404 Advanced in Objective-C ,从36分起讲相关的东西,喔,看不懂,那还是看看这个吧,在《iOS 7 Programming Pushing the Limits》的 Further Reading: objc_explain_Non-pointer_isa 部分谈论了这个问题。

  2. 《谈 Objective-C Block 的实现》

  内容非常翔实,特别是关于 Block 类型的部分,强烈建议做下文章开头提到的测试:Objective-C Blocks Quiz。

  3. 消息发送和消息转发

  消息发送比较好理解,先了解下 runtime 吧,可以查看官方文档《Objective-C Runtime Guide》。之前学习其他语言的时候还没有关注过调用函数的背后发生了什么,在 Objective-C 中,在对象上调用方法称为发送消息,比如[receiver message];这行代码,编译的时候编译器将之转换为对 底层 C 函数objc_msgSend 的调用:objc_msgSend(receiver, selector);在运行时,调用哪个方法则完全由 runtime 决定,甚至在运行时可以替换调用的方法,这是 Objective-C 被称为动态语言的根本原因。对于消息转发,说实话我现在还不知道这个的应用场景,看到的大部分博客都是说消息转发给了你补救措施来应对没有没有实现的方法防止 Crash 或者实现类似多继承的机制,我有个疑惑,干嘛不实现那个方法,而要在代价很大的转发机制里处理呢。在《Effective Objective-C 2.0》一书第 12 条 tip 中用 @dynamic 演示了实现动态方法解析的例子来说明消息转发的意义,老实说,我还是没有理解这个的意义。这里有个对官方文档的中文翻译和一些注解。

  4. Implement of category and method

  找到了来自这位比我厉害得多的90后:《刨根问底Objective-C Runtime(3)- 消息 和 Category》(文章原来的链接放进来跟简书的处理有冲突,这里给的是博客地址,而不是这篇文章的具体地址,不过很好找)。

  5. Class load

  可以看这篇博客:《Objective-C Class Loading and Initialization》,看了下作者的 Github,原来是我以前 follow 过的国外程序员,看人家的 repo 和星星,质量有保障,再看博客文章列表,有很多深入底层的内容,一座宝矿啊。另外在《Effective Objective-C 2.0》书中第51节《精简 initialize 与 load 的实现》中也讨论了这个问题,当初看完一头雾水,如今终于能看懂啦。

  Core Data: 大量数据多线程同步

  这个问题我已经单独成篇放到这里了,添加了更多的基础知识和介绍。

  第一步:搭建 Core Data 多线程环境

  这个问题首先要解决的是搭建 Core Data 多线程环境。NSManagedObjectContext 不是线程安全的,你不能随便地开启一个后台线程访问 managed object context 进行数据操作就管这叫支持多线程了。Core Data 对多线程的支持比较好,NSManagedObjectContext 在初始化时可以指定并发模式,有三种选项:

  1.NSConfinementConcurrencyType

  这种模式是用于向后兼容的,使用这种模式时你应该保证不能在其他线程使用 context,但这点很难保证,不推荐使用。此模式在 iOS 9中已经被废弃。

  2.NSPrivateQueueConcurrencyType

  在一个私有队列中创建并管理 context。

  3.NSMainQueueConcurrencyType

  其实这种模式与第 2 种模式比较相似,只不过 context 与主队列绑定,也因此与应用的 event loop 很亲密。当 context 与 UI 更新相关的话就使用这种模式。

  搭建多线程 Core Data 环境的方案一般如下,创建一个 NSMainQueueConcurrencyType 的 context 用于响应 UI 事件,其他涉及大量数据操作可能会阻塞 UI 的就使用 NSPrivateQueueConcurrencyType 的 context。环境搭建好了,如何实现多线程操作?官方文档《Using a Private Queue to Support Concurrency》为我们做了示范,在 private queue 的 context 中进行操作时,应该使用以下方法:

  func performBlock(_ block: () -> Void)//在私有队列中异步地执行 Blcok func performBlockAndWait(_ block: () -> Void)//在私有队列中执行 Block 直至操作结束才返回

  要在不同线程中使用 managed object context 时,不需要我们创建后台线程然后访问 managed object context 进行操作,而是交给 context 自身绑定的私有队列去处理,我们只需要在上述两个方法的 Block 中执行操作即可。而且,在 NSMainQueueConcurrencyType 的 context 中也应该使用这种方法执行操作,这样可以确保 context 本身在主线程中进行操作。

  第二步:数据的同步操作

  多 context 同步最简单的方案如下:

  NSManagedObjectContext 在执行保存操作后会发出 NSManagedObjectContextDidSaveNotification,包含了 context 所有的变化信息,包括新增的、更新的以及删除的对象的信息;而 mergeChangesFromContextDidSaveNotification(_ notification) 方法则用于合并其他 context 中发生的变化。

  如果 context 并未观察其他 context 的 NSManagedObjectContextDidSaveNotification通知,且保存时,persistent store 已经被其他 context 更改过,那么很可能存在差异,此时同步就有了以下几种选择:选择保存 context 中的版本或者使用 persistent store 的版本替换 context 的版本,又或是将两者的版本融合。这种同步方式由 NSManagedObjectContext 的 mergePolicy属性决定。

  1.NSErrorMergePolicy

  默认策略,有冲突时保存失败,persistent store 和 context 都维持原样,并返回错误信息,是唯一反馈错误信息的合并策略。

  2.NSMergeByPropertyStoreTrumpMergePolicy

  当 persistent store 和 context 里的版本有冲突,persistent store 里的版本有优先权, context 里使用 persistent store 里的版本替换,但是 context 里没有冲突的变化则不会受到影响。

  3.NSMergeByPropertyObjectTrumpMergePolicy

  与上面相反,context 里的版本有优先权,persistent store 里使用 context 里的版本替换,但是 persistent store 里没有冲突的变化不受影响。

  4.NSOverwriteMergePolicy

  用 context 里的版本强制覆盖 persistent store 里的版本。

  5.NSRollbackMergePolicy

  放弃 context 中的所有变化并使用 persistent store 中的版本进行替换。

  同步是件很复杂的事情,实际上还是需要根据实际需要来选择同步方案。上面两种方案中第一种概念简单实现容易,第二种比较复杂相对危险,需要谨慎选择同步策略。还有一点需要注意,如果需要跨线程使用 managed object,那么不要直接在其他 context 里使用该 managed object,而应该通过该对象的 objectID 将该对象 fetch 到 context 里。

  最后,搞定大量数据

  多线程和同步问题解决,最后的难点:大量数据。大量数据意味着需要我们关注内存占用和性能,写代码时需要记得以下规则:

  1.尽可能缓存需要的数据,不相关的数据保持 faults状态。

  2.fetch 时尽可能精准,少引入不相关的数据。

  3.构建多 context 时尽量将同类 managed object 集中,最大限度减少合并需求。

  4.提升操作效率,对Asynchronous Fetch, Batch Update,Batch Delete 等新特性尽可能利用。

  多线程编程

  在 iOS 编程中,这几种情况下需要处理多线程:UI 事件必须在主线程里进行,其他的可以放在后台进行;而进行一些耗时长或阻塞线程的任务,最后放进后台线程里进行。iOS 的多线程技术有这么几种:线程,GCD 和 NSOperationQueue。线程这种技术比较复杂,而多线程编程向来是「复杂必死」,推荐尽可能使用后二者,但线程有个后二者没有的优势:能够精确保证任务执行的时间。GCD 全称是 Grand Central Dispatch, 是 libdispatch 这个库的外部代号,基于 C 的底层来实现;而NSOperationQueue,通称操作队列,是基于 GCD 实现的。GCD 能做的 NSOperationQueue 基本上都能做,而且还有些 GCD 中不易实现的特性,如挂起、取消任务,虽然在 iOS 8 中,GCD 也提供了取消任务的功能,但在 GCD 中任务的挂起和取消都有较大的局限性;虽然大多数情况下应该使用抽象级别更高的 API,也就是 NSOperationQueue,但处理一般的后台任务我偏爱 GCD,主要是 GCD 搭配 Blcok 使用简单,非常方便。如何选择,下面两个链接对此问题的讨论值得一看:

  StackOverflow: NSOperation vs. Grand Central Dispatch

  Blog: When to use NSOperation vs. GCD

  另外,还推荐这些文章:objc 的并发编程专题《Concurrent Programming》 及中文翻译版本;雷纯锋的博客《iOS 并发编程之 Operation Queues》;NSHipster 的《NSOperation》。

  设计模式

  评价 Delegate, Notification, KVO 几种设计模式的优缺点

  我不觉得这个问题是个好问题,与其比较这几个设计模式的优缺点,不如谈它们各自的特点比较好,因为它们是为了解决某类问题才设计出来的,有各自适合的使用场景。另外,给个 iOS 中设计模式的介绍:iOS Design Patterns。

  为什么出题目都喜欢把这三个设计模式拿来对比呢?Notification 和 KVO都是用于协助对象间的通信:某个对象监听某个事件的发生,当某个事件发生时,该对象会得到通知然后做出响应。这几句话大概是以前看过的书本上说的。如果你以前没接触过设计模式,第一次学习时总是能够看到事件、响应这类模糊的词汇,看得你云里雾里,好吧,我说的是我。 但 delegate,应该说没有监听的功能,而是当事件发生或时机到了,要求 delegate 对象做点什么。刚开始学习 OC 的时候,一本书中将 delegate比喻为助手,那时候不怎么理解,现在觉得这个比喻十分恰当。虽然delegate 模式在 OC 中随处可见,在UIViewController 类中广泛存在,但在开发 FaceAlbum 的过程中只遇到过一次自定义 protocol/delegate 的情况,后来还是用 KVO 取代了。相对于 Notification 和 KVO 模式,使用 delegate 模式你会明确知道对象的 delegate 能干什么,因为要成为 某个对象的delegate,该对象得遵守指定的 protocol,protocol 指定了 delegate 对象需要实现的方法。

  Notification和 KVO两者都需要监听事件的对象(早期看见事件就犯晕,如今写来觉得用这个词挺顺手的)去注册,delegate则需要 delegate 对象遵守指定的 protocol;Notification 中监听者向一个单例对象NSNotificationCenter注册,NSNotificationCenter类似一个广播中心,接受任何对象的注册,后者则向要监听的对象注册,一对一,这两者都不需要对象之间有联系,而 delegate 则需要通信的对象通过变量联系;NSNotification模式里监听的对象与被监听的对象通信是通过 NSNotificationCenter 这个中介,而KVO 里,不能说两者是直接通信的,我没有了解过过 KVO 是如何实现通信的,从表面上看两者就那么心灵感应一般,这是系统替我们实现的,而delegate,由于通过变量连接,直接向 delegate 发送消息即可,在这点上,NSNotification不需要通信双方知道对方,而后两者则不然;在响应事件时,NSNotification和 KVO 模式里都是在注册时指定响应方法,而 delegate 则在 protocol 里预定义了响应方法。

  说了这么多,不直观,说个实际场景,比如在 UICollectionView 里选择 cell 的时候,希望 title 能够跟踪选中 cell 的数量。这里用NSNotification和 KVO 都能实现,但是我更喜欢 KVO,感觉更优雅,因为使用NSNotification模式的话,选中一个 cell 的时候要在选择的方法里手动发布通知,而 KVO,只要对观察的属性实现 KVO 兼容的方法就可以了;而delegate,自己做自己的 delegate,呃。而面对一些系统里的事件,比如键盘的出现与消失,图片库的变化,使用NSNotification更加自然,因为 KVO 于课课家限于对对象属性的跟踪。

ios面试题 看了就知道哪方面需要加强上机练习相关推荐

  1. 超全!iOS 面试题汇总

    超全!iOS 面试题汇总 2015-10-20 CocoaChina 作者:Job_Yang 之前看了很多面试题,感觉要不是不够就是过于冗余,于是我将网上的一些面试题进行了删减和重排,现在分享给大家. ...

  2. 经过阿里,百度一面,二面后,我总结了150道iOS面试题

    经过阿里,百度一面,二面后,我总结了150道iOS面试题. 金三银四已经过去,根据统计,很多人都会选择在三月四月跳槽,原因有很多,企业年后会有大量员工离职,员工觉得老公司待遇不怎么样?薪资不够高,想换 ...

  3. 最新iOS面试必看题视频教程(附大神简历要素)

    2019独角兽企业重金招聘Python工程师标准>>> 本文是由尚学堂iOS学院总结的ios开发者在求职时会遇到的一些面试题 ,并通过实际代码演练将课程详尽的讲解出来,希望对学习io ...

  4. iOS面试题-UI篇

    http://www.360doc.com/content/20/0630/21/31460730_921535347.shtml 这里有关于面试方面汇总:关于iOS面试题汇总(栏目持续更新)http ...

  5. 史上最全的iOS面试题及答案

    史上最全的iOS面试题及答案 1.写一个NSString类的实现 + (id)initWithCString:(c*****t char *)nullTerminatedCString encodin ...

  6. 那些著名或非著名的iOS面试题(中)

    接上篇:那些著名或非著名的iOS面试题(上),本文继续介绍一些著名或非著名的iOS面试题. 1. 反转二叉树,不用递归 /*** Definition for a binary tree node.* ...

  7. 2019最新iOS面试题及答案

    1. Object-C的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-C的类不可以多重继承;可以实现多个接口,通过实现 ...

  8. iOS 面试题--转自唐巧

    iOS 面试题(一)寻找最近公共 View 题目:找出两个 UIView 的最近的公共 View,如果不存在,则输出 nil . 分析:这其实是数据结构里面的找最近公共祖先的问题. 一个UIViewC ...

  9. 2018 iOS 面试题大全(补充完整版)

    原文地址:2018 iOS 面试题大全 由于原作者并没有继续更新,这里我转过来继续更新下 整理的一些iOS面试相关问题,持续更新,敬请关注 2018 iOS面试题大全---全方面剖析面试 1.2018 ...

最新文章

  1. 几种Normalization算法.md
  2. SQLAlchemy实现插入数据(使用前端页面)
  3. GO库安装报错解决:unrecognized import path golang.org/x/net (https fetch: dial tcp i/o timeout
  4. Android -- Intent
  5. 想做个手机app,大家帮忙提些建议~thx
  6. 自动化测试用例设计原则
  7. java栈和队列_栈和队列的面试题Java
  8. Linux宝库上线,有木有get到你?
  9. java项目-第35期在线购书商城系统【毕业设计】
  10. 启动失败java.lang_关于jeesite启动失败的问题java.lang.UnsupportedClassVersionError
  11. 使用八爪鱼工具爬取京东当前所有手机信息存入mysql
  12. jsmind 线条_使用jsMind显示思维导图
  13. SAP 消息号 KE391:在 CO-PA中分配条件类型PR00的问题
  14. 王者荣耀服务器未响应 小米,10月23日小米手机更新王者荣耀失败 小米更新不了新赛季怎么办...
  15. Linux man指令查询文档设定成中文
  16. ROCBOSS开源微社区轻论坛类源码
  17. initramfs实作
  18. android 教你如何创建马甲包
  19. 1.spring security简单的demo-适合萌新
  20. 【2016 下半年总结】 拨开云雾见天日——专注提升自己最重要

热门文章

  1. Ant Design Vue DatePicker 日期选择框 限制可选时间
  2. 未来计算机的畅享300,新学期畅享作文300字(通用5篇)
  3. 如何从iTunes Store赠送音乐,电影等
  4. 自然人代开是什么政策,怎么操作呢?
  5. 3dmax:3dmax的软件两大常用工具之基本三维实体(标准基本体、扩展基本体、复合对象)之详细攻略
  6. 微信公众号如何设置开发者密码(APPSecret)?
  7. Myflight航班查询系统
  8. 百度地图海量点尺寸和大小
  9. 商业综合体能耗在线监测管理系统_商场管理平台
  10. 量化 ZIG函数的python实现