iOS面试题分享(一)

这是我参与8月更文挑战的第10天,活动详情查看: 8月更文挑战sql

dSYM你是如何分析的?

dSYM是什么?

Xcode编译项目以后,咱们会看到一个同名的dSYM文件,dSYM是保存十六进制函数地址映射信息的中转文件,咱们调试的symbols都会包含在这个文件中,而且每次编译项目的时候都会生成一个新的dSYM文件,位于/User/<用户名>/Library/Developer/Xcode/Archives目录下,对于每个发布版本咱们都颇有必要保存对应的Archives文件;数据库

dSYM文件有什么用?

当咱们软件release模式打包或上线后,不会像咱们在Xcode中那样直观的看到用崩溃的错误,这个时候咱们就须要分析crash report文件了,iOS设备中会有日志文件保存咱们每一个应用出错的函数内存地址,经过XcodeOrganizer能够将iOS设备中的DeviceLog导出成crash文件,这个时候咱们就能够经过出错的函数地址去查询dSYM文件中程序对应的函数名和文件名。大前提是咱们须要有软件版本对应的dSYM文件,这也是为何咱们颇有必要保存每一个发布版本的Archives文件了。编程

如何将文件一一对应?

每个xx.appxx.app.dSYM文件都有对应的UUID, crash文件也有本身的UUID,只要这三个文件的UUID-致,咱们就能够经过他们解析出正确的错误函数信息了。api

  • 1.查看xx.app文件的UUID, terminal 中输入命令: dwarfdump --uuid xx.app/xx (xx表明你的项目名)
  • 2.查看xx.app.dSYM文件的UUID,在terminal中输入命令: dwarfdump --uuid xx.app.dSYM
  • 3.crash文件内第一行Incident Identifier就是该crash文件的UUID

多线程有哪几种?

多线程分类

  • pthread
    • 一套通用的多线程API
    • 适用于Unix\Linux\Windows等系统
    • 跨平台,可移植
    • 使用难度大
    • 使用语言:C语言
    • 使用频率:几乎不使用
    • 线程生命周期:开发者进行管理
  • NSThread
    • 面向对象
    • 简单易用,可直接操做线程
    • 使用语言:OC语言
    • 使用频率:偶尔使用
    • 线程生命周期:开发者进行管理
  • GCD
    • 替换NSThread的技术
    • 充分利用了设备的多核(自动)
    • 使用语言:C语言
    • 使用频率:常用
    • 线程生命周期:自动管理
  • NSOperation
    • 基于GCD
    • 比GCD多了一些更简单实用的功能
    • 使用更加面向对象
    • 使用语言:OC语言
    • 使用频率:常用
    • 线程生命周期:自动管理

多线程的原理

同一时间,CPU只能处理1条线程,只有1条线程在工做(执行)多线程并发(同时)执行,实际上是CPU快速地在多条线程之间调度(切换)若是CPU调度线程的时间足够快,就形成了多线程并发执行的 假象思考:若是线程很是很是多,会发生什么状况?CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源每条线程被调度执行的频次会下降(线程的执行效率下降)markdown

多线程的优势

能适当提升程序的执行效率能适当提升资源利用率(CPU、内存利用率)网络

多线程的缺点

线程须要占用必定的内存空间(默认状况下,主线程占用1M,子线程占用512KB),若是开启大量的线程,会占用大量的内存空间,下降程序的性能线程越多,CPU在调度线程上的开销就越大程序设计更加复杂:好比线程之间的通讯、多线程的数据共享;数据结构

GCD与NSOperation的比较

  • 一、GCD是底层的C语言构成的API,而NSOperationQueue及相关对象是Objc的对象。在GCD中,在队列中执行的是由block构成的任务,这是一个轻量级的数据结构;而Operation做为一个对象,为咱们提供了更多的选择;
  • 二、在NSOperationQueue中,咱们能够随时取消已经设定要准备执行的任务(固然,已经开始的任务就没法阻止了),而GCD无法中止已经加入queueblock(实际上是有的,但须要许多复杂的代码);
  • 三、NSOperation可以方便地设置依赖关系,咱们可让一个Operation依赖于另外一个Operation,这样的话尽管两个Operation处于同-个并行队列中,但前者会直到后者执行完毕后再执行;
  • 四、咱们能将KVO应用在NSOperation中,能够监听一个Operation是否完成或取消,这样子能比GCD更加有效地掌控咱们执行的后台任务;
  • 五、在NSOperation中,咱们可以设置NSOperationpriority优先级,可以使同一个并行队列中的任务区分前后地执行,而在GCD中,咱们只能区分不一样任务队列的优先级,若是要区分block任务的优先级,也须要大量的复杂代码;
  • 六、咱们可以对NSOperation进行继承,在这之,上添加成员变量与成员方法,提升整个代码的复用度,这比简单地将block任务排入执行队列更有自由度,可以在其之.上添加更多自定制的功能。总的来讲,Operation queue提供了更多你在编写多线程程序时须要的功能,并隐藏了许多线程调度,线程取消与线程优先级的复杂代码,为咱们提供简单的API入口。从编程原则来讲,-般咱们须要尽量的使用高等级、封装完美的API,在必须时才使用底层API。可是我认为当咱们的需求可以以更简单的底层代码完成的时候,简洁的GCD或许是个更好的选择,而Operation queue为咱们提供能更多的选择。
  • 七、NSOperation拥有更多的函数可用,具体查看api。NSOperationQueue是在GCD基础.上实现的,只不过是GCD更高一层的抽象
  • 八、在NSOperationQueue中,能够创建各个NSOperation之间的依赖关系。
  • 九、NSOperationQueue支持KVO。能够监测operation是否正在执行(isExecuted)、是否结束(isFinished) , 是否取消(isCanceld)
  • 十、GCD只支持FIFO的队列,而NSOperationQueue能够调整队列的执行顺序(经过调整权重)。NSOperationQueue能够方便的管理并发、NSOperation之间的优先级。
  • 总结
    • 使用NSOperation的状况:各个操做之间有依赖关系、操做须要取消暂停、并发管理、控制操做之间优先级,限制同时能执行的线程数量.让线程在某时刻中止/继续等。
    • 使用GCD的状况:通常的需求很简单的多线程操做,用GCD均可以了,简单高效。从编程原则来讲,通常咱们须要尽量的使用高等级、封装完美的API,在必须时才使用底层API。当需求简单,简洁的GCD或许是个更好的选择,而Operation queue为咱们提供能更多的选择。

单例的弊端

  • 优势:
    • 一个类只被实例化一次,提供了对惟一实例的受控访问
    • 节省系统资源
    • 容许可变数目的实例
  • 缺点:
    • 一个类只有一个对象,可能形成责任太重,在必定程度上违背了单一职责原则
    • 因为单例模式中没有抽象层,所以单例类的扩展有很大困难
    • 滥用单例将带来一些负面问题,如:为了节省资源将数据库链接池对象设计为单例类,可能会致使共享链接池对象的程序过多而出现链接池溢出;若是实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将致使对象状态的丢失

介绍下App启动的完成过程

App启动过程

  • 解析Info.plist
  • 加载相关信息,例如闪屏
  • 沙盒创建、权限检查
  • Mach-O加载
  • 若是是二进制文件,寻找合适当前CPU类别的部分
  • 加载全部依赖的Mach-O文件(递归调用Mach-o加载方法)
  • 定位内部、外部指针引用,例如字符串,函数等
  • 执行声明为attribute(constructor)的C函数
  • 加载类的扩展中的方法
  • C++静态对象加载,调用Objc+load函数

程序执行

  • main函数
  • 执行UlApplicationMain函数
  • 建立UIApplication对象
  • 建立UIApplicationDelegate对象并复制
  • 读取配置文件info.plist,设置程序启动的一些属性
  • 建立应用程序的Main Runloop循环
  • UlApplicationDelegate对象开始处理监听事件
  • 程序启动以后,首先调用application.didFinishLaunchingWithOptions:方法
  • 果info.plist中配置了启动的storyBoard的文件名,则加载storyboard文件
  • 若是没有配置,则根据代码建立UIWindow ->rootViewController->显示

App启动过慢,多是哪些因素引发的?

  • 影响启动性能的因素App启动过程当中每一个步骤都会影响启动性能,可是有些部分所消耗的时间少之又少,另外有些部分根本没法避免,考虑到投入产出比,咱们只列出咱们能够优化的部分: main(函数以前耗时的影响因素
  • 动态库加载越多,启动越慢。
  • ObjC类越多,启动越慢
  • Cconstructor函数越多,启动越慢
  • C++静态对象越多,启动越慢
  • ObjC+load越多,启动越慢实验证实,在ObjC类的数目 同样多的状况下,须要加载的动态库越多,App启动就越慢。一样的,在动态库同样多的状况下,ObjC的类越多,App的启动也越慢。须要加载的动态库从1个上升到10个的时候,用户几乎感知不到任何分别,但从10个, 上升到100个的时候就会变得十分明显。同理,100个类和1000个类, 可能也很难查察以为出,但1000个类和10000个类的分别就开始明显起来。一样的,尽可能不要写atribute((constrcror))C函数,也尽可能不要用到C++的静态对象;至于ObjC+load方法,彷佛你们已经习惯不用它了。任何状况下,能用dispatch_ _once()来完成的,就尽可能不要用到以上的方法。main()函数以后耗时的影响因素
  • 执行main()函数的耗时
  • 执行applicationWillFinishLaunching的耗时
  • rootViewController及其childViewController的加载、view及其subviews的加载applicationWillFinishLaunching的耗时

0x8badf00d表示什么?

  • 0x8badf00d:该编码表示应用是由于发生watchdog超时而被iOS终止的。一般是应用花费太多时间而没法启动、终止或响应用系统事件。
  • 0xbad22222:该编码表示VolP应用由于过于频繁重启而被终止
  • Oxdead10cc: 该代码代表应用由于在后台运行时占用系统资源,如通信录数据库不释放而被终止。
  • Oxdeadfa11:该代码表示应用是被用户强制退出的。根据苹果文档,强制退出发生在用户长按开关按钮直到出现“滑动来关机”,而后长按Home按钮。强制退出将产生包含0xdeadfa11异常编码的崩溃日志,由于大多数是强制退出是由于应用阻塞了界面。

怎么防止反编译?

  • 本地数据加密: iOS应用防反编译加密技术之一:对NSUserDefaults,sqlite存储文件数据加密,保护账号和关键信息
  • URL编码加密: iOS应用防反编译加密技术之二:对程序中出现的URL进行编码加密,防此URL被静态分析
  • 网络传输数据加密: iOS应用防反编译加密技术之三:对客户端传输数据提供加密方案,有效防止经过网络接口的拦截获取数据
  • 方法体,方法名高级混淆: iOS应用防反编译加密技术之四:对应用程序的方法名方法体进行混淆,保证源码被逆向后没法解析代码
  • 程序结构混排加密: iOS应用防反编译加密技术之五:对应用程序逻辑结构进行打乱混排,保证源码可读性降到最低
  • 借助第三方APP加固

你了解哪些第三方原理或者底层知识?

RuntimeRunloopblockSDWebImageAFNYYCacheGCD等等底层实现多线程

相关文章
相关标签/搜索