iOS开发面试中需要牢牢记住的几个知识点

helloworld_52729984
• 阅读 592

如何分析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一致,我们就可以通过他们解析出正确的错误函数信息了。

  • 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语言
    • 使用频率:经常使用
    • 线程生命周期:自动管理

如果你正在跳槽或者正准备跳槽不妨动动小手,添加一下咱们的交流群1012951431来获取一份详细的大厂面试资料为你的跳槽多添一份保障。

多线程的原理

同一时间,CPU只能处理1条线程,只有1条线程在工作(执行)多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换)如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象思考:如果线程非常非常多,会发生什么情况?CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源每条线程被调度执行的频次会降低(线程的执行效率降低)

多线程的优点

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

多线程的缺点

线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能线程越多,CPU在调度线程上的开销就越大程序设计更加复杂:比如线程之间的通信、多线程的数据共享;

GCD与NSOperation的比较

  • 1、GCD是底层的C语言构成的API,而NSOperationQueue及相关对象是Objc的对象。在GCD中,在队列中执行的是由block构成的任务,这是一个轻量级的数据结构;而Operation作为一个对象,为我们提供了更多的选择;

  • 2、在NSOperationQueue中,我们可以随时取消已经设定要准备执行的任务(当然,已经开始的任务就无法阻止了),而GCD没法停止已经加入queueblock(其实是有的,但需要许多复杂的代码);

  • 3、NSOperation能够方便地设置依赖关系,我们可以让一个Operation依赖于另一个Operation,这样的话尽管两个Operation处于同-个并行队列中,但前者会直到后者执行完毕后再执行;

  • 4、我们能将KVO应用在NSOperation中,可以监听一个Operation是否完成或取消,这样子能比GCD更加有效地掌控我们执行的后台任务;

  • 5、在NSOperation中,我们能够设置NSOperationpriority优先级,能够使同一个并行队列中的任务区分先后地执行,而在GCD中,我们只能区分不同任务队列的优先级,如果要区分block任务的优先级,也需要大量的复杂代码;

  • 6、我们能够对NSOperation进行继承,在这之,上添加成员变量与成员方法,提高整个代码的复用度,这比简单地将block任务排入执行队列更有自由度,能够在其之.上添加更多自定制的功能。总的来说,Operation queue提供了更多你在编写多线程程序时需要的功能,并隐藏了许多线程调度,线程取消与线程优先级的复杂代码,为我们提供简单的API入口。从编程原则来说,一般我们需要尽可能的使用高等级、封装完美的API,在必须时才使用底层API。但是我认为当我们的需求能够以更简单的底层代码完成的时候,简洁的GCD或许是个更好的选择,而Operation queue为我们提供能更多的选择。

  • 7、NSOperation拥有更多的函数可用,具体查看api。NSOperationQueue是在GCD基础.上实现的,只不过是GCD更高一层的抽象

  • 8、在NSOperationQueue中,可以建立各个NSOperation之间的依赖关系。

  • 9、NSOperationQueue支持KVO。可以监测operation是否正在执行(isExecuted)、是否结束(isFinished) , 是否取消(isCanceld)

  • 10、GCD只支持FIFO的队列,而NSOperationQueue可以调整队列的执行顺序(通过调整权重)。NSOperationQueue可以方便的管理并发、NSOperation之间的优先级。

    总结

  • 使用NSOperation的情况:各个操作之间有依赖关系、操作需要取消暂停、并发管理、控制操作之间优先级,限制同时能执行的线程数量.让线程在某时刻停止/继续等。

  • 使用GCD的情况:一般的需求很简单的多线程操作,用GCD都可以了,简单高效。从编程原则来说,一般我们需要尽可能的使用高等级、封装完美的API,在必须时才使用底层API。当需求简单,简洁的GCD或许是个更好的选择,而Operation queue为我们提供能更多的选择。

如果你正在跳槽或者正准备跳槽不妨动动小手,添加一下咱们的交流群1012951431来获取一份详细的大厂面试资料为你的跳槽多添一份保障。

单例的弊端

优点:

  • 一个类只被实例化一次,提供了对唯一实例的受控访问

  • 节省系统资源

  • 允许可变数目的实例

缺点:

  • 一个类只有一个对象,可能造成责任过重,在一定程度上违背了单一职责原则

  • 由于单例模式中没有抽象层,因此单例类的扩展有很大困难

  • 滥用单例将带来一些负面问题,如:为了节省资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失

介绍下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等等底层实现

文末推荐:iOS热门文集

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
helloworld_52729984
helloworld_52729984
Lv1
上穷碧落下黄泉,两处茫茫皆不见。
文章
2
粉丝
1
获赞
2