iOS底层原理(一):OC的本质、KVO原理、Category原

2020-08-26  本文已影响0人  冰风v落叶
一、OC对象的本质
知识点
将Objective-C代码转换为C\C++代码:
xcrun  -sdk  iphoneos  clang  -arch  arm64  -rewrite-objc  OC源文件  -o  输出的CPP文件
如果需要链接其他框架,使用-framework参数。比如-framework UIKit
创建一个实例对象,至少需要多少内存?
#import <objc/runtime.h>
class_getInstanceSize([NSObject class]);

创建一个实例对象,实际上分配了多少内存?
#import <malloc/malloc.h>
malloc_size((__bridge const void *)obj);
image.png image.png

上图中的关系用文字表示是这样的:

- instance的isa指向class

- class的isa指向meta-class

- meta-class的isa指向基类的meta-class

- class的superclass指向父类的class,如果没有父类,superclass指针为nil

- meta-class的superclass指向父类的meta-class,基类的meta-class的superclass指向基类的class

- instance调用对象方法的轨迹:isa找到class,方法不存在,就通过superclass找父类

- class调用类方法的轨迹:isa找meta-class,方法不存在,就通过superclass找父类

PS: 这里的方法列表、属性列表、协议列表都归属于class_rw_t可读写的类信息中,而成员变量列表归属于class_ro_t只读的类信息中,所以方法列表、属性列表、协议列表都是可以通过RunTime动态增加的,而成员变量列表就不能动态增加!!!这就是Category为什么只能增加方法,不能增加成员变量的核心原因(通过关联方式增加的成员变量是通过全局变量来存储的)

面试题
二、KVO
知识点
实例对象和类对象的内存布局.png
以监听age属性为例,KVO的触发流程:
[self willChangeValueForKey:@"age"];
super.age = age;  //原来的方法实现
[self didChangeValueForKey:@"age"];  
-----didChangeValueForKey方法内部会调用observer的observeValueForKeyPath:ofObject:change:context:方法
面试题
三、Category
知识点
面试题

(1). 调用时机不同:

1>. load是runtime加载类和分类的时候调用,只会被调用一次
2>. initialize是类第一次接收到消息的时候调用,当子类没有initialize方法时,就会调用父类的,所以可能会被调用多次

(2). 调用方式不同:

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

(3). 调用顺序不同:

1>.load:先调用类的load方法,先编译的先调用,在调用load之前会先调用父类的load方法;然后在调用分类的load方法,也是先编译的先调用;分类的load方法不会覆盖本类的load方法
2>.initialize:先初始化父类,之后再初始化子类。如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次),如果分类实现了+initialize,就覆盖类本身的+initialize调用。
四、Block
知识点
self.block = ^{
     NSLog(@"%@",self);
};
__weak typeof(self) weakSelf = self;
self.block = ^{
  NSLog(@"%@",weakSelf);
};
面试题

- 1. Block的本质是什么?

答: Block是封装了函数调用以及函数调用环境的OC对象

- 2. __block的作用是什么?

答:__block可以解决block内部无法修改auto修饰的变量的问题,编译器会将__block修饰的变量包装成一个对象

- 3. block的属性修饰词为什么是copy?

答: block使用copy其实是MRC留下来的一个传统,在MRC下,block创建在栈区, 使用copy就能把它放到堆区, 这样在作用域外调用该block程序就不会崩溃;而在ARC下block的属性修饰词是copy和strong都可以,ARC会在需要的时候,自动帮我们把block从栈上拷贝到堆上

- 4. block中修改NSMutableArray中的元素,需不需要添加__block?

答: 不需要,仅仅修改数组中的元素是不需要加__block的,如果是给array重新赋值新的数组,这时候才需要加__block

上一篇 下一篇

猜你喜欢

热点阅读