有文事者,必有武备

28 iOS 图像渲染原理

https://www.jianshu.com/p/a81d48e0e44a

 

27 HTTP1.0、HTTP1.1 和 HTTP2.0 的区别

https://www.cnblogs.com/heluan/p/8620312.html

https://www.jianshu.com/p/25b762d58e66

26 十大经典算法

http://www.runoob.com/w3cnote/ten-sorting-algorithm.html 十大经典算法

https://www.jianshu.com/p/95d224c4d13e  七大查找算法

25 位运算

https://www.jianshu.com/p/19d7b1afcdcc

24 isEqual与hash

https://www.jianshu.com/p/915356e280fc

https://www.jianshu.com/p/502c5da1f170 

23 self和super的理解

https://www.jianshu.com/p/ad9f1f3971d7

https://www.jianshu.com/p/60352a5eb940

        self 是类的隐藏参数,指向当前调用方法的这个类的实例。而 super 是一个 Magic Keyword, 它本质是一个编译器标示符,和 self 是指向的同一个消息接受者。

         上面的例子不管调用[self class]还是[super class],接受消息的对象都是当前 Son *xxx 这个对象。而不同的是,super是告诉编译器,调用 class 这个方法时,要去父类的方法,而不是本类里的。

        当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用 super 时,则从父类的方法列表中开始找。然后调用父类的这个方法。

         当调用 [self class] 时,实际先调用的是 objc_msgSend函数,

第一个参数是 Son当前的这个实例,然后在 Son 这个类里面去找 - (Class)class这个方法,

没有,去父类 Father里找,

也没有,最后在 NSObject类中发现这个方法。

而 - (Class)class的实现就是返回self的类别,故上述输出结果为 Son。

 

 而当调用 [super class]时, 会转换成objc_msgSendSuper函数。

第一步先构造 objc_super 结构体,

        结构体的第一个成员就是 self 。 第二个成员是 (id)class_getSuperclass(objc_getClass(“Son”)) , 实际该函数输出结果为 Father。

第二步是去 Father这个类里去找 - (Class)class,没有,然后去NSObject类去找,找到了。

        最后内部是使用 objc_msgSend(objc_super->receiver, @selector(class))去调用, 此时已经和[self class]调用相同了,故上述输出结果仍然返回 Son。

 

22 编译过程

当一个xcode工程build之后一般会执行如下几个步骤:

  • 预处理
  • 语法和语义分析
  • 生成代码和优化
  • 汇编
  • 链接

iOS编译采用Clang作为编译器前端,LLVM作为编译器后端。流程如下:

Clang的任务:预处理、词法分析、语法分析、语义分析、静态分析、生成中间代码。

预处理:以#开头的代码预处理。包括引入的头文件和自定义宏。
词法分析:每一个.m源文件的声明和定义从string转化为特殊的标记流。
语法分析:将标记流解析成一颗抽象语法树( abstract syntax tree-AST)。
静态分析:包含类型检查和其他检查。
中间代码生成:生成LLVM代码。

 

LLVM的任务:将代码进行优化并产生汇编代码。
汇编器:将可读的汇编代码转换为机器代码,最终创建一个目标对象.o文件。
链接器的任务:把目标文件和库相连,最终输出可运行文件:a.out。

链接:https://www.jianshu.com/p/65901441903e
 

21 dyld加载过程

dyld加载过程

  1. 设置运行环境
  2. 加载共享缓存
  3. 实例化主程序
  4. 加载插入的动态库
  5. 链接主程序
  6. 链接插入的动态库
  7. 执行弱符号绑定
  8. 执行初始化方法
  9. 查找入口点并返回

20 super

https://blog.csdn.net/shihuboke/article/details/73930935

符合oc 继承类 初始化规范 super 同样也是这样, [super init] 去self 的super 中调用init super 调用 superSuper 的init 。直到根类 NSObject 中的init ,根类中init 负责初始化 内存区域 向里面添加 一些必要的属性,返回内存指针, 这样 延着继承链 初始化的内存指针 被从上 到 下 传递,在不同的子类中向块内存添加 子类必要的属性,直到 我们的 A 类中 得到内存指针,赋值给slef 参数, 在if (slef){//添加A 的属性 }
 

struct objc_super { 
          id   receiver; 
          Class   superClass; 
};

self和super底层实现原理:

- 当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用 super 时,则从父类的方法列表中开始找,然后调用父类的这个方法。

- 当使用 self 调用时,会使用 objc_msgSend 函数: id objc_msgSend(id theReceiver, SEL theSelector, ...)。第 一个参数是消息接收者,第二个参数是调用的具体类方法的 selector,后面是 selector 方法的可变参数。以 [self setName:] 为例,编译器会替换成调用 objc_msgSend 的函数调用,其中 theReceiver 是 self,theSelector 是 @selector(setName:),这个 selector 是从当前 self 的 class 的方法列表开始找的 setName,当找到后把对应的 selector 传递过去。

- 当使用 super 调用时,会使用 objc_msgSendSuper 函数:id objc_msgSendSuper(struct objc_super *super, SEL op, ...)第一个参数是个objc_super的结构体,第二个参数还是类似上面的类方法的selector。

 

19 OC 消息发送机制

lookUpImpOrForward

lookUpImpOrForward会返回一个imp,它的函数实现比较长,但是注释写的非常清楚。它的实现主要由以下几步(这里直接从缓存获取开始):

  1. 通过cache_getImp从缓存中获取方法,有则返回,否则进入第2步;
  2. 通过getMethodNoSuper_nolock从类的方法列表中获取,有加入缓存中并返回,否则进入第3步;
  3. 通过父类的缓存和父类的方法列表中寻找是否有对应的imp,此时会进入一个for循环,沿着类的父类一直往上找,直接找到NSObject为止。如果找到返回,否则进入第4步;
  4. 进入方法决议(method resolve)的过程即调用_class_resolveMethod,如果失败,进入第5步;
  5. 在缓存、当前类、父类以及方法决议都没有找到的情况下,Objective-C还为我们提供了最后一次翻身的机会,调用_objc_msgForward_impcache进行方法转发,如果找到便加入缓存;如果没有就crash。

上述过程中有几个比较重要的函数:

 消息机制流程图
链接:
https://juejin.im/post/5c87a218f265da2dd868cfcd

https://www.jianshu.com/p/fdd8f5225f0c 

 

18 缓存淘汰策略FIFO、LFU、LRU 算法

(1)缓存数据和目标数据的一致性问题。

(2)缓存的过期策略(机制)。

其中,缓存的过期策略涉及淘汰算法。常用的淘汰算法有下面几种:

(1)FIFO:First In First Out,先进先出

(2)LRU:Least Recently Used,最近最少使用

(3)LFU:Least Frequently Used,最不经常使用

链接:https://www.jianshu.com/p/660f61084d9b
 

https://www.cnblogs.com/sunsky303/p/9214223.html

https://www.jianshu.com/p/4cd5509eec3d

https://www.jianshu.com/p/33e572da4b58

https://www.cnblogs.com/argenbarbie/p/5401133.html

17 锁的原理

https://www.jianshu.com/p/0b8f6a5e66bc

16 编译过程

参考:

https://objccn.io/issue-6-1/

https://objccn.io/issue-6-3/

https://objccn.io/issue-6-2/

https://www.jianshu.com/p/65901441903e

http://blog.chinaunix.net/uid-31439230-id-5763397.html

https://blog.csdn.net/Future_One/article/details/81882359

 

1 预处理

符号化 (Tokenization)

宏定义的展开

#include 的展开

2 语法和语义分析

将符号化后的内容转化为一棵解析树 (parse tree)

解析树做语义分析

输出一棵抽象语法树(Abstract Syntax Tree* (AST))

3生成代码和优化

将 AST 转换为更低级的中间码 (LLVM IR)

对生成的中间码做优化

生成特定目标代码

输出汇编代码

4 汇编器

将汇编代码转换为目标对象文件。

5 链接器

将多个目标对象文件合并为一个可执行文件 (或者一个动态库)

15 IOS中线程所占用的内存空间

https://www.jianshu.com/p/adef1ef4ff39

线程栈
线程的每个方法被执行的时候,都会同时创建一个帧(Frame)用于存储本地变量表、操作栈、动态链接、方法出入口等信息。每一个方法的调用至完成,就意味着一个帧在VM栈中的入栈至出栈的过程。如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果VM栈可以动态扩展(VM Spec中允许固定长度的VM栈),当扩展时无法申请到足够内存则抛出OutOfMemoryError异常。
原文:https://blog.csdn.net/u013851082/article/details/70314778 
 

14 ARC与MRC

https://www.jianshu.com/writer#/notebooks/15534033/notes/42885788

 

13 objc_object & objc_class

https://www.jianshu.com/p/c67964d85e91

参考: https://www.jianshu.com/p/8ea1e5169d7a   《objc源码解析-ObjectiveC对象结构》

参考:https://blog.csdn.net/u013378438/article/details/80493158  《基本数据结构:objc_object & objc_class》

 

12  Tagged Pointer


Tagged Pointer 的引用主要解决内存浪费和访问效率的问题。所以其有以下特点:

  • Tagged Pointer 专门用于存储小的对象,例如:NSString、NSNumber 和 NSDate。
  • Tagged Pointer指针的值不再是堆区地址,而是真正的值。所以,实际上它不再是一个对象了,它只是一个披着对象皮的普通变量而已。所以,它的内存并不存储在堆中,也不需要 malloc 和 free。
  • 在内存读取上有着 3 倍的效率,创建时比以前快 106 倍。

          如此可见,Apple 引入了 Tagged Pointer 不仅仅节省了64位处理器的占用内存空间,还提高了运行效率。
使用注意点

  • Tagged Pointer 并不是真正的指针,由测试代码的变量内存分布截图,都可表明其对应的 isa 指针已经指向 0x0 地址。所以如果你直接访问 Tagged Pointer 的 isa 成员的话,编译时期将会有警告。可以通过调用 isKindOfClass 和 object_getClass,避免直接访问对象的 isa 变量。

 
https://www.jianshu.com/p/dcbf48a733f9

https://www.jianshu.com/p/c9089494fb6c

https://www.jianshu.com/p/e354f9137ba8

 

11 类对象

1, objc_object中的isa 指的是对象的类;
2, objc_class中的isa只的是类的元类;
3, superClass是一层层集成的,到最后NSObject的superClass是nil.而NSObject的isa指向根元类,这个跟元类的isa指向它自己,而它的superClass是NSObject,也就是最后形成一个环,这个环让我想起了先有鸡还是先有蛋的问题.
4, mateClass也是相互继承的.
5, 这个逻辑就想着objc_class的struct,里面有个isa属性,还有个super_class属性,他俩都是指针,其实在objc_class的定义中也能看出来,每一个objc_class都有isa,但是不一定会有super_class,近三天每天想一次.

https://www.jianshu.com/p/20f1251916b9

https://www.jianshu.com/p/9e975a1cab93

https://www.jianshu.com/p/4ae681091e2a

 

10

在32位系统中:

int 占4个字节 
long 占4个字节 
NSInteger 是int的别名,占4个字节 
long long 占8个字节 
int32_t 是int的别名,占4个字节 
int64_t 是long long的别名,占8个字节

在64位系统中:

int 占4个字节 
long 占8个字节 
NSInteger 是long的别名,占8个字节 
long long 占8个字节 
int32_t 是int的别名,占4个字节 
int64_t 是long long的别名,占8个字节

由于long和NSInteger的字节数变了,所以在兼容的时候可能会导致溢出


原文:https://blog.csdn.net/zhao18933/article/details/46925675  

9 runloop models

1. kCFRunLoopDefaultMode: 默认 mode,通常主线程在这个 Mode 下运行。
2. UITrackingRunLoopMode: 追踪mode,保证Scrollview滑动顺畅不受其他 mode 影响。
3. UIInitializationRunLoopMode: 启动程序后的过渡mode,启动完成后就不再使用。
4: GSEventReceiveRunLoopMode: Graphic相关事件的mode,通常用不到。
5: kCFRunLoopCommonModes: 占位mode,作为标记DefaultMode和CommonMode用。

8 进程间通信

https://segmentfault.com/a/11900000024003291、CFMessagePort 
2、XPC可以被libxpc C API访问,或者是NSXPCConnection OC API
3、XPC提供了一个便捷的方法来从dispatch_data_t数据类型进行转换,这样从GCD到XPC的工作流程就简化了:
4、NSPasteboard
5、Distributed Notifications:APICFNotificationCenterGetDistributedCenter   
6、LightMessaging :http://iphonedevwiki.net/index.php/LightMessaging  ,https://github.com/rpetrich/LightMessaging

7 NSTimer 循环引用问题

https://www.jianshu.com/p/2fe076e5e255   小心NSTimer中的内存泄漏

利用 NSTimer 的 userInfo 传入 block

在 Nstimer 的回调中,使用 block ,用block 循环引用的方式 处理 。

6 id 与 NSObject,  instancetype

 https://www.jianshu.com/p/a1f377dfc85a

https://www.jianshu.com/p/3b7efa02bdf4

 

5 启动优化总结

关于app启动优化,可以从几方面入手:

  1. 减少不必要的framework;
  2. 清理项目中没有使用到的代码、类,避免冗余代码;
  3. 慎用+load,第三方库已经使用了够多的+load方法(objection,rn…),在写代码时尽量用+initialize代替+load;
  4. 梳理流程,优化代码,启动模块化。耗时操作不要在主线程;
  5. 本地缓存。首页的数据离线化,优先展示本地缓存数据,等待网络数据返回之后更新缓存并展示;
  6. 懒加载,使用时再去创建;
  7. 网络优化,减少接口请求,接口合并,使用ip直连,除去DNS解析耗时,使用protobuf协议,使用http2协议。

4 内存优化

1.关于UITableView
(1)善于使用UITableViewCell的重用机制
(2)优化UITableViewCell高度计算

2 懒加载(延迟加载)
3  关于图片的处理
(1)缓存图片  一个是用imageNamed,二是用imageWithContentsOfFile。

(2)调整图片大小
(3)代码渲染 or 直接获取
          图片的解码字节对齐。
 (4)图片尺寸的大小 和 imageView 的大小不一致 也会消耗性能,用ImageIO 进行优化
4 数据处理

      在项目开发中,我们会使用到各种格式的数据,例如 JSON、XML 等。还有各种各样的数据结构,例如数组、链表、字典、集合等。使用正确的数据格式和使用正确的数据结构,会减少我们的资源消耗。

(1)选择正确的数据格式
App与网络进行交互时,常常采用 JSON 或者 XML 类型的数据格式。

(2)选择正确的数据结构

不同的数据结构,处理数据的速度是不同的。
数组 NSArray NSMutableArray:有序的一组值。使用索引来查询很快,使用值查找很慢, 插入/删除很慢。
字典 NSDictionary NSMutableDictionary:存储键值对。用键来查找比较快。
集合 NSSet NSMutableSet:无序的一组值。用值来查找很快,插入/删除很快。

5 View的处理
(1)避免使用过于复杂的xib 
(2)正确设置View的背景
(3)设定Shadow Path

      如果用下面代码给 view.layer 添加一个shadow:

      这会使Core Animation 不得不在后台得出图形并加好阴影之后再去渲染,这会开销很大。
如果使用shadowPath则会避免这种问题:

6 合理使用Autorelease Pool

7 正确处理缓存
8  iOS使用的是低内存处理机制Jetsam,这是一个基于优先级队列的机制。

9 CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类。用CGPath来定义想要绘制的图形,CAShapeLayer会自动渲染。它可以完美替代我们的直接使用Core Graphics绘制layer,对比之下使用CAShapeLayer有以下优点:

渲染快速。CAShapeLayer 使用了硬件加速,绘制同一图形会比用 Core Graphics 快很多。
高效使用内存。一个 CAShapeLayer 不需要像普通 CALayer 一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。
不会被图层边界剪裁掉。
不会出现像素化。

10 画布ImageContext   消耗内存大    通过 @autoreleasepool 来解决 
11  光栅化,是把GPU的操作转到CPU上了,生成位图缓存 。当 shouldRasterize 设成 true 时,layer 被渲染成一个 bitmap,并缓存起来,等下次使用时不会再重新去渲染了。实现圆角本身就是在做颜色混合(blending),如果每次页面出来时都blending,消耗太大,这时shouldRasterize = yes,下次就只是简单的从渲染引擎的 cache 里读取那张 bitmap,节约系统资源。
   可见,如果要节约内存,尽量少用光栅化。

12 临时变量过多,建议使用autoreleasepool 以便及时释放;

https://www.jianshu.com/p/5e95e70948f7   

https://www.jianshu.com/p/1f6bc977d97c
https://mp.weixin.qq.com/s/q1jufAuZytF3yi6tE2jY0g 先弄清楚这里的学问,再来谈iOS内存管理与优化(二)

3 iOS 修改图片尺寸的方法

https://www.jianshu.com/p/ba45f5539e4e  

1. 画布ImageContext   消耗内存大    通过 @autoreleasepool 来解决 

2. image I/O 创建省略图  

https://www.jianshu.com/p/de7b6aede888  iOS的5种图片缩略技术以及性能探讨

2 寄宿图 与 CAShapeLayer 与  drawRect

https://www.jianshu.com/p/bee0d5efc964  drawRect 内存暴增原因,如何优化绘图

 内存恶鬼drawRect - 谈画图功能的内存优化

1 解码方式 

1、CGContextDrawImage方式(CoreGraphics)
它接受一个原始的位图参数 imageRef ,最终返回一个新的解压缩后的位图 newImage ,中间主要经过了以下三个步骤:

使用 CGBitmapContextCreate 函数创建一个位图上下文;
使用 CGContextDrawImage 函数将原始位图绘制到上下文中;
使用 CGBitmapContextCreateImage 函数创建一张新的解压缩后的位图。

2、CGImageGetDataProvider方式(ImageIO)
  1.CGImageSourceCreateWithData(data) 创建ImageSource。
  2.CGImageSourceCreateImageAtIndex(source) 创建一个未解码的 CGImage。
   3.CGImageGetDataProvider(image) 获取这个图片的数据源。
   4.CGDataProviderCopyData(provider) 从数据源获取直接解码的数据。
ImageIO 解码发生在最后一步,这样获得的数据是没有经过颜色类型转换的原生数据(比如灰度图像)。

 
链接:https://www.jianshu.com/p/e9843d5b70a2
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值