咱们先来解释一下苹果官方给开发者提供的这张图bash
例如咱们建立个本身的类 LWPerson *person = [[LWPerson alloc] init];
每一个类都有本身的isa
,它指向对应的了[LWPerson Class]
,[LWPerson Class]
也有本身的isa
,它则指向对应的元类meta
;这里解释一下两个问题spa
Q : Instance(类对象),class(类),meta(即meta-class元类) 里面各存着这么设计
A : Instance
存着一个isa
指向class
,还存着本身的成员变量;class
里存有isa
,superclass
,属性、对象方法、协议、成员变量等;meta
里存在isa,superclass
,类方法等;如图(图片引用自李明杰老师)3d
isa
要这样指来指去,这样有什么好处
A : 例如这段代码指针
LWPerson *person = [[LWPerson alloc] init];
person.age = 20;
persom.height = 180;
[person sing];
[person dance];
[person rap];
复制代码
其中age
和height
都是每一个LWPerson
私有的,每建立一个LWPerson
均可能不同,可是sing
,dance
,rap
方法是每个LWPerson
共有。因此当建立LWPerson
对象后,只需isa
和成员变量,全部的方法都放在LWPerson
的类里,对象经过isa
找到对应类的的方法,这样能够大大的节省LWPerson
对象所占用的内存。这里LWPerson
类的isa
指向LWPerson
的元类,类方法就存在元类里,也很好的解释了通常状况下 类方法为何不能使自己的成员变量,由于存在类对象上;code
接回以前的继续说:每一个类都存有一个superclass
指针,这很好理解,子类若是找不到对应的方法,便会顺着superclass
指针找到对应的父类。meta
的也同样自己没有的类方法也会去寻找父类的类方法,这样一直一级一级往上传,一直传到Root Class
, Root Class
的元类比较特殊,苹果设计它的isa
指向本身,superclass
指向Root Class
,若是Root Class
也找不到方法,就会报一个咱们很熟悉的错误 unrecognized selector sent to instance 0x600001a3a5b0
cdn
可能上面说的比较多比较乱,咱们能够举个栗子再捋一次 首先,咱们建立个类LWPerson
继承于NSObject
。对象
LWPerson *person = [[LWPerson alloc] init];
复制代码
在建立LWPerson
的时候,咱们用的[LWPerson alloc]
本质就是 LWPerson
类经过isa
去meta
里找类方法,可是找不到!就再经过meta
的superclass
找到它的父meta
即NSObject
的meta
, NSObject
的类方咱们很容易就能够找到alloc
。init
也是同理,咱们在[LWPerson alloc]
后,它实际上返回的是一个LWPerson
的对象,它自己也没有init
对象方法,因此找它的父类NSObject
的对象方法init
blog
咱们也能够在LWPerson.h
中声明一个-(void)sing
方法,但不写实现,这样person
对象就会去LWPerson
的类里找sing
方法,但没实现sing
方法,就会顺着superclass
去NSObject
到对象方法,但NSObject
也没有sing
方法,因此继续往上找到了Root Class
,但Root Class
也没有sing
方法,因此指向nil
,系统报错 unrecognized selector sent to instance
。 继承