秒速赛车:iOS进阶(二)Objec

  每一个对象都是一个类的实例,在Objective-C中,每一个对象都有一个名为isa的指针,指向该对象的类。每一个类描述了一系列它的实例的特点,包括成员变量的列表、成员函数的列表等。每一个对象都可以接受到消息,而对象能够接受到的消息列表保存在它所对应的类中。

  通过注释我们看到objc_object代表一个对象的实例,在对象实例中我们看到了isa指针,验证了我们刚才说的话。

  根据面向对象的设计原则,所有事物都应该是对象,所以在Objective-C中,每一个类实际上也是一个对象,每一个类也有一个名为isa的指针,每一个类也可以接收消息,例如代码[NSObject alloc],就是向NSObject这个类发送名为alloc的消息。

  objc_class代表一个类,从上面代码中可以看出类中有一个isa指针的。前面说到isa指针会执行它的类,那类中的isa指针指向什么呢?因为类也是一个对象,所以它也必须是另一个类的实例,这个类就是元类(metaclass),所以isa指针指向的是它的元类。元类保存了类的方法列表。当一个类的方法被调用时,元类会首先查找它本身是否有该类方法的实现,如果没有,则该元类会向它的父类查找该方法,这样可以一直找到继承链的头。

  如前面所说元类也是一个对象,那么元类的isa指针指向谁呢?Objective-C为了设计上的完整,所有的元类的isa指针都会指向一个根元类(root metaclass),秒速赛车官网:iOS进阶(二)Objective-C底层原理根元类的isa指针指向自己,这样就形成一个闭环。上面说到,一个对象能够接收的消息列表是保存在它所对应的类中的。秒速赛车官网:在实际编程中,我们几乎不会遇到向元类发消息的情况,那它的isa指针在实际上很少用到。

  再来看看继承关系,由于类方法的定义是保存在元类中,而方法调用的规则是,如果该类没有一个方法的实现,则向它的父类继续查找。所以,为了保证父类的类方法在子类中可以被调用,所有子类的元类都会继承父类的元类,简单来说就是类对象和元类对象有着同样的继承关系。

  Objective-C运行时的核心就在于消息分派器objc_msgSend,消息分派器把选择器映射为函数指针,并调用被引用的函数。 要想理解objc_msgSend的背后原理,先来理解下NSInvocation这个类。

  NSInvocation是命令模式的一种传统实现,它把一个目标、一个选择器、一个方法签名和所有的参数都塞进一个对象里,这个对象可以先存储起来,以备将来调用。当NSInvocation被调用时,它会发送信息,Objective-C运行时会找到正确的方法实现来执行。我们通过一个例子来理解下NSInvocation的作用,比如[NSObject alloc],此时会发送一个alloc消息,这条消息都包含什么内容呢?它怎么找到alloc的实现方法呢?这些都是通过NSInvocation来完成的,它包含了消息要传递的内容,也告诉了该怎么找到对应的方法实现。

  解释一下什么是方法实现?一个方法实现(IMP)是一个指向具有如下签名的C函数的函数指针,注意是指针。

  NSInvocation包含了一个目标和选择器,目标是一个可接受的对象,选择器则是被发送的消息。比如[NSObject alloc],目标就是NSObject,选择器就是alloc。一个选择器大致是一个方法的名称,之所以说是大致是因为选择器不必精确映射到方法。比如[NSString length]和[NSData length]会映射到不同方法的实现,但他们拥有相同的选择器。

  NSInvocation还包含一个方法签名(NSMethodSignature),它封装了一个方法的返回类型和参数类型,记住它不包括方法名称,只有返回类型和参数类型。你可以手动创建一个方法签名,如下:

  但是应该尽可能少使用signatureWithObjCTypes:方法,获得方法签名常用的方法是为它请求一个类或实例,比如可以使用methodSignatureForSelector:方法从实例中请求实例方法签名,或者从类中请求类方法签名。也可以使用instanceMethodSignatureForSelector:方法从一个类中获取实例方法签名。两个方法有点绕口,我们通过一个例子来看下区别:

  最后,NSInvocation还包含了所有的参数。至。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.yingkedasmt.com/ganhuo/608.html