iOS知识点总结

多线程:

进程和线程的区别:进程是火车, 线程是车厢。进程间不共享上下文, 同一进程下的线程共享进程的上下文
• 同步(sync):阻塞当前线程, 任务立即执行
• 异步(async):可以在新的线程中执行任务, 具备开启新线程的能力。
• 串行:同一时间只有一个任务执行
• 并行:同一时间有多个任务执行(多核)
• 并发:单核通过时间片轮转宏观上实现并行的机制


数据结构:

• 堆:逻辑结构完全二叉树, 可以用一维数组实现, 这种数据结构方便求极值。向上调整算法/向下调整算法
• 栈:先进后出, 可以用一维数组或者链表实现

内存:

• 堆:动态分配, 主要为了解决栈空间释放后变量也被释放的问题
• 栈:逻辑上先进后出, 由系统控制。


Swift:

函数调用方式:

静态, 动态。动态包括函数表调用和消息发送。扩展(extension)没有函数表, 所以只能使用静态或者消息发送的方式。结构体及其扩展静态调用;类默认函数表调用, final-静态, @objc-函数表, dynamic-消息发送;类扩展默认使用静态调用, 类扩展+@objc/dynamic-消息发送

Swift与OC区别:
  1. Swift是静态语言, 有类型推断, OC是动态语言
  2. Swift面向协议编程, OC面向对象编程
  3. Swift注重值类型, OC注重引用类型
  4. Swift支持泛型, OC只支持轻量泛型
  5. Swift支持静态派发(效率高)、动态派发(函数表派发、消息派发), OC支持动态派发(消息派发)
  6. Swift支持函数式编程
  7. Swift的协议不仅可以被类实现, 也可以被structenum实现
  8. Swift有元组类型、支持运算法重载
  9. Swift支持命名空间
  10. Swift支持默认参数(函数)
  11. Swift比OC代码更简洁
  12. 值类型优化:如写时拷贝

Block:

全局block在数据区, 没有捕获变量的block原本应该在栈, 但是编译器优化, 转移到了数据区。捕获变量的block变量会在堆, 但如果是block对象, 因为没有变量名, 所以不会再其他地方调用, 会在栈。捕获变量的block对象如果对其使用copy, 会在堆。(MRC下, 如果不对捕获变量的block使用COPY, 就在栈)


layoutSubviews调用时机:

有尺寸且添加到父View上时, 父视图是ScrollView且滚动时, 改变尺寸时


load、initialize方法的区别:

• 调用方式

  1. load是根据函数地址直接调用
  2. initialize是通过objc_msgSend调用

• 调用时刻

  1. load是runtime加载类、分类的时候调用(只会调用1次)
  2. initialize是类第一次接收到消息的时候调用, 每一个类只会initialize一次,

如果有SubClass继承Class.
则在SubClass第一次收到消息时, 会先调用SubClass-initialize, 再调用Class-initialize;
如果SubClass没有重写initialize, 则在SubClass-initialize过程中触发Class-initialize, 表现为Class-initialize被调用了两次. 即一个类向上的继承树上有N个类, 在接收到消息时就会触发N+1initialize, 如果某个类没有重写initialize, 则会向上调用最近的initialize
综上: 重写initialize时需用考虑使用dispatchonce避免重复调用和初始化.


热启动与冷启动

参考: http://events.jianshu.io/p/783d8b3ef884//www.greatytc.com/p/4c1adabc8b90

  1. 热启动:就是按下home键的时候, app还存在一段时间, 这时点击app马上就能恢复到原状态, 这种启动我们称为热启动。当APP 启动时需要的 dylibs 仍然停留在设备的磁盘缓存的时候,这个时候就是热启动,热启动的速度会更快。
  2. 冷启动:app被kill掉之后, 重新打开启动过程为冷启动。

性能优化:


冷启动:

冷启动可大致分为两个阶段, 分别为main函数之前、main之后到didFinishLaunching执行完毕, 很多时候, 首页的完成展示前的阶段可包含在启动阶段内. 上述两个阶段为pre-mainmain.

pre-main阶段:
pre-main的过程
  1. 加载mach-o可执行文件
  2. 加载dyld到App进程,
  3. 加载动态库(包括所依赖的所有动态库)
  4. Rebase 内部指针调整。
  5. Bind 把指针正确的指向Image外部的内容。通过符号表查找
  6. 初始化Objective-C Runtime, Objc运行时的初始化处理, 包括Objc相关类的注册、category注册、selector唯一性检查
  7. 其他初始化, 包括执行了+load()方法、attribute((constructor))修饰的函数调用、创建C++静态全局变量
针对pre-main的优化:
  1. 尽量缩小mach-o的大小(待研究) - 1
  2. 减少动态库, 在动态库较多时将多个动态库合并 - 3
  3. 减少Objc类, category的数量, 清除用不到的类、函数 - 4, 6
  4. 使用dispatchonce+initialize代替+load, 尽量减少attribute((constructor))的调用, 也可以考虑用dispatchonce+initialize代替 - 7
  5. 二进制重排.
t1.png
main阶段:
  1. dyld调 main()
  2. 调UIApplicationMain()
  3. 调applicationWillFinishLaunching
  4. 调didFinishLaunchingWithOptions

这部分包含大量APP配置和业务代码, 梳理好其内容, 将能延后的内容尽量延后, 此阶段可用的办法有:

  1. 延后部分代码执行
  2. 使用闪屏优化体验
  3. 内嵌启动首页展示数据
  4. 多线程

热启动

  1. 数据优化,将耗时操作做异步处理。
  2. 检查NSUserDefaults的存储,NSUserDefaults实际上是在Library文件夹下会生产一个plist文件,加载的时候是整个plist配置文件全部load到内存中。所以非常频繁的存取大量数据也是有可能导致APP启动卡顿的

卡顿

参考 https://zhuanlan.zhihu.com/p/502990984

手机成像过程

产生卡顿是由于屏幕的成像显示导致, 而屏幕画面的显示离不开手机的CPU和GPU. CPU主要负责计算, 比如说界面的布局排版, 文字的大小和颜色, 图片显示的解码等操作都需要CPU计算, CPU将计算好的数据提交给GPU, GPU就将CPU计算好的数据进行渲染。因为屏幕显示的数据是特定格式的,只有通过GPU渲染过的数据才能显示在屏幕上;GPU把渲染过的数据放到帧缓存区, 视频控制器从帧缓存区读取数据显示到屏幕上.


卡顿.png
卡顿的主要原因

CPU和GPU所花费的时间太长从而造成俗称的丢帧(掉帧). 垂直同步信号的发射频率是固定的, 信号发出, 表明着即将显示数据。若是期间, CPU或GPU有一步耗时较长(第3帧的渲染), 垂直信号已发出, 可是GPU尚未渲染完, 那么就是显示渲染好的第2帧数据, 连续显示相同的帧, 就形成了画面卡顿; 第3帧会在第4次同步信号过来时再显示。这就是卡顿的根本原因.

1. CPU和GPU

CUP(Central processing Unit,中央处理器)
对象的创建和销毁、对象属性的调整、布局计算、文本的计算和排版、图片的格式转换和解码、图像的绘制(Core Graphics)

GPU (Graphics Processing Unit,图形处理器)
纹理的渲染

优化:
  • 尽可能减少CPU、GPU资源消耗
  • 尽量用轻量级的对象,比如用不到事件处理的地方,可以考虑使用CALayer取代UIView
  • 不要频繁地调用UIView的相关属性,比如frame、bounds、transform等属性,尽量减少不必要的修改
  • 尽量提前计算好布局,在有需要时一次性调整对应的属性,不要多次修改属性
  • Autolayout会比直接设置frame消耗更多的CPU资源
  • 图片的size最好刚好跟UIImageView的size保持一致
  • 控制一下线程的最大并发数量
  • 尽量避免短时间内大量图片的显示,尽可能将多张图片合成一张进行显示
  • GPU能处理的最大纹理尺寸是4096x4096,一旦超过这个尺寸,就会占用CPU资源进行处理,所以纹理尽量不要超过这个尺寸
  • 尽量减少视图数量和层次
  • 减少透明的视图(alpha<1),不透明的就设置opaque为YES
  • 尽量把耗时的操作放到子线程(文本尺寸、图片处理)
2. 离屏渲染(尽量避免出现离屏渲染)

在OpenGL中,GPU有2种渲染方式
On-Screen Rendering:当前屏幕渲染,在当前用于显示的屏幕缓冲区进行渲染操作
Off-Screen Rendering:离屏渲染,在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作

离屏渲染消耗性能的原因

1、需要创建新的缓冲区
2、离屏渲染的整个过程,需要多次切换上下文环境,先是从当前屏幕(On-Screen)切换到离屏(Off-Screen);等到离屏渲染结束以后,将离屏缓冲区的渲染结果显示到屏幕上,又需要将上下文环境从离屏切换到当前屏幕

哪些操作会触发离屏渲染?

光栅化,layer.shouldRasterize = YES
遮罩,layer.mask
? 圆角,同时设置layer.masksToBounds = YES、layer.cornerRadius大于0(考虑通过CoreGraphics绘制裁剪圆角,或者叫UI提供圆角图片)
阴影,layer.shadowXXX (如果设置了layer.shadowPath就不会产生离屏渲染)。


耗电

  1. 尽可能降低CPU、GPU功耗
  2. 少用定时器
  3. 优化I/O操作
  4. 尽量不要频繁写入小数据,最好批量一次性写入
  5. 读写大量重要数据时,考虑用dispatch_io,其提供了基于GCD的异步操作文件I/O的API。用dispatch_io系统会优化磁盘访问
  6. 数据量比较大的,建议使用数据库(比如SQLite、CoreData)

网络

  1. 减少、压缩网络数据
  2. 如果多次请求的结果是相同的,尽量使用缓存
  3. 使用断点续传,否则网络不稳定时可能多次传输相同的内容
  4. 网络不可用时,不要尝试执行网络请求
  5. 让用户可以取消长时间运行或者速度很慢的网络操作,设置合适的超时时间
  6. 批量传输,比如,下载视频流时,不要传输很小的数据包,直接下载整个文件或者一大块一大块地下载。如果下载广告,一 次性多下载一些,然后再慢慢展示。如果下载电子邮件,一次下载多封,不要一封一封地下载

定位

  1. 如果只是需要快速确定用户位置,最好用CLLocationManager的requestLocation方法。定位完成后,会自动让定位硬件断电
  2. 如果不是导航应用,尽量不要实时更新位置,定位完毕就关掉定位服务
  3. 尽量降低定位精度,比如尽量不要使用精度最高的kCLLocationAccuracyBest
  4. 需要后台定位时,尽量设置pausesLocationUpdatesAutomatically为YES,如果用户不太可能移动的时候系统会自动暂停位置更新
  5. 尽量不要使用startMonitoringSignificantLocationChanges,优先考虑startMonitoringForRegion:
  6. 用户移动、摇晃、倾斜设备时,会产生动作(motion)事件,这些事件由加速度计、陀螺仪、磁力计等硬件检测。在不需要检测的场合,应该及时关闭这些硬件
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容

  • 内容均转自标哥的技术博客 只是按照自己的习惯进行简单的整理 1、对数组中的元素去重复 1.第一种方法:开辟新的内存...
    Kk太阳阅读 5,608评论 0 21
  • # 运行时 ``` 1、程序中任何代码都会被转化成runtime的C代码执行,如[target doSomeThi...
    _叮叮当当__阅读 158评论 0 0
  • 多线程有哪几种,常见的应用场景 SDWebImage的原理和实现机制 事件的传递和响应机制 UITableView...
    十六月阅读 1,141评论 0 9
  • UIKit 1.UIView 和 CALayer 是什么关系? UIView 继承 UIResponder,而 U...
    远行客丶阅读 1,019评论 0 3
  • 1. iOS单例的实现方式? 之前总是这样写: static Singleton *shareSingleton ...
    飞哥漂流记阅读 229评论 0 0