问题整理

1、代理的效率高,还是KVO的效率高?

代理的效率高,因为代理不会动态的生成类

2、怎么拿到一个对象的类对象,怎么拿到一个类的元类对象

isa指针指向的就是类对象
object_getClass(self.per1) == self.per1.isa

 NSLog(@"类对象  %@  %@",
          object_getClass(self.per1),
          object_getClass(self.per2));

object_getClass(object_getClass(self.per1)) == self.per1.isa.isa

 NSLog(@"元类对象  %@  %@",
          object_getClass(object_getClass(self.per1)),
          object_getClass(object_getClass(self.per2)));

3.1、添加KVO的对象的元类和不添加KVO的对象的元类是否是一个?

不是同一个,添加KVO的元类是 NSKVONotifying_类名

image.png

3.2、iOS用什么方式实现一个对象的KVO?(KVO的本质是什么)

比如给Person对象的age属性添加KVO监听

1、利用Runtime生成Person子类<NSKVONotifying_Person>,并且让对象的isa指针指向NSKVONotifying_Person
2、当修改Personage属性时候,会调用Foundation_NSSet***ValueAndNotify函数
2.1、调用willChangeValueForKey
2.2、调用super的属性setAge:方法
2.3、调用didChangeValueForKey
2.3.1、内部调用- (void)observeValueForKeyPath: ofObject:change: context:;

3.3、怎么手动触发KVO监听?

调用对象的

[self.per1 willChangeValueForKey:@"age"];
[self.per1 didChangeValueForKey:@"age"];
image.png

3.4、直接修改成员变量会触发KVO吗?

@interface Person : NSObject
{
    @public
    NSString *_name;
}

/// 名字
@property (nonatomic, copy) NSString * name;
@end
self.per->_name = @"333";

不能,必须要触发set方法,或者【手动触发】KVO才可以,详情见上面。

怎么才能实现,直接修改成员变量,触发KVO呢?

[self.per willChangeValueForKey:@"name"];
self.per->_name = @"333";
[self.per didChangeValueForKey:@"name"];

4.1、KVC setValue: forKeyPath:的实现原理

未命名文件.png

4.2、KVC操作能不能触发KVO的监听

@interface Person : NSObject
{
    @public
    int _age;
}

@end

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    Person *per = [[Person alloc] init];
    
    [per addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    
    [per setValue:@10 forKeyPath:@"age"];
    
    [per removeObserver:self forKeyPath:@"age"];
    
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    NSLog(@"keyPath = %@   %@",keyPath,change);
}

可以触发<满足KVC的任何一种方式都可以触发>,可能调用KVC的时候内部触发了

[per willChangeValueForKey:@"age"];
per->_age = 123;
[per didChangeValueForKey:@"age"];
触发KVO

4.3、KVC valueForKey:的原理

KVC valueForKey: 的原理.png

4.4、怎么给一个属性赋值,并且不触发set方法

@interface Person : NSObject

/// name
@property (nonatomic, copy) NSString * name;

@end

- (void)setName:(NSString *)name {
    _name = [name copy];
    
    NSLog(@"触发了set方法   name === %@",_name);
}

 Person *per = [[Person alloc] init];
[per setValue:@"123" forKey:@"_name"];
    
NSLog(@"per.name === %@",per.name);
    

5、一个NSObject对象占用多少内存

NSObject对象中就一个isa指针,一个指针占用内存的大小(64bit环境下8个字节,32bit环境下4个字节)

5.1、对于一个自定义的对象,占用多大的空间呢?
@interface Person : NSObject
{
    @public
    int _age;
    int _height;
}
@end
struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int _age;
    int _height;
};

16字节 = isa(8) + int(4) +int(4)

5.2、对于一个如下自定义的对象,占用多大的空间呢?

在64bit的环境下,一个Person对象和一个Student对象占用多少内存空间?

// Person
@interface Person : NSObject
{
    @public
    int _age;
}
@end

@implementation Person
@end

// Student
@interface Student : Person
{
    @public
    int _height;
}
@end

@implementation Student
@end

\color{red}{Person 占用16个字节}
\color{red}{Student 占用16个字节}

分析.png

代码分析:

struct NSObject_IMPL {
    Class isa;  // 8个字节
};

struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;    // 8个字节
    int _age;   // 4个字节
};  // 16个字节<内存对齐>

struct Student_IMPL {
    struct Person_IMPL Person_IVARS;    // 16个字节,空余四个
    int _height;    // 4个字节
};  // 16个字节<内存对齐>

6、对象的isa指针指向哪?

instance的isa指向class
class的isa指向meta-class
meta-class的isa指向基类meta-class
底层原理总结 — isa和superclass

7、OC的类信息都放在哪里?

成员变量的具体值存放在instance对象中
对象方法,协议,属性,成员变量信息放在class对象中
类方法信息存放在meta-class对象中

8、判断class是否为meta-class

Class metaClass = object_getClass([Person class]);
Class class = [Person superclass];
NSLog(@"%d  %d",class_isMetaClass(metaClass),class_isMetaClass(class));

结果:

1  0
9.1、Category的原理是啥?

Category编译之后的底层结构是struct category_t,里面存储着分类的对象方法,类方法,协议,属性信息。
在程序运行的时候,runtime会将Category的数据合并到类中<类对象和元类对象>

9.2、当我们调用Category的方法是怎么调用的?

参考第一条问题答案。
调用对象方法:通过对象的isa找到类对象,找到类对象中的方法,调用
调用类方法:通过类对象的isa找到元类对象,扎到元类对象中的类方法,调用

9.3、当Category中和类中存在相同方法的时候,最终调用的是哪一个?

调用的是Category中的方法
因为类方法列表已经放到整体方法列表的后面了。
所以调用相同方法的时候,会优先遍历到分类中的方法

image.png
9.4、当多个Category中存在相同方法的时候,最终调用的是哪一个?

会调用后编译的分类中的方法
因为runtime将分类中的方法列表合并到类对象中的时候,是倒叙遍历的,所以后被编译的分类中的方法列表优先被加到类对象中。


image.png
image.png

那么分类的编译顺序在哪里查看呢?


image.png
9.5、CategoryClass Extension有啥区别?
#import "Person.h"

@interface Person()
@property (nonatomic, copy) NSString *address;
@end

@implementation Person
- (void)run {
    NSLog(@"Person");
}
@end

Class Extension在编译的时候,他的数据已经包含在了Class中了
Category中的信息要等到runtime的时候才会合并到Class

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容