ios - objectC 的isa 详解

来源:互联网 发布:为什么需要云计算 编辑:程序博客网 时间:2024/05/22 00:42

每个Objective-C对象都有一个隐藏的数据结构,这个数据结构是Objective-C对象的第一个成员变量,它就是isa指针。

在NSObject.h里面: 

@interface NSObject <NSObject> {

    Class isa  OBJC_ISA_AVAILABILITY;

}

再点开 Class 的定义:

struct objc_class {

    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__

    Class super_class                                        OBJC2_UNAVAILABLE;

    const char *name                                         OBJC2_UNAVAILABLE;

    long version                                             OBJC2_UNAVAILABLE;

    long info                                                OBJC2_UNAVAILABLE;

    long instance_size                                       OBJC2_UNAVAILABLE;

    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;

    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;

    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;

    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;

#endif

}

这一些定义对于懂的人自然懂,不会的人根本看不懂。建议看完下面的例子,再点开参考里面的链接仔细看一遍。

 

现在我们知道的是,对于我们新建的一个类,都会有一个隐藏的属性isa,可以通过它进行一些访问。

我们现在新建一个类Parent,继承于NSObject, 里面有成员方法-(void)selectorP,类方法+(void)ClassSelectorP。

再新建一个类Child,继承于Parent,里面有成员方法-(void)selectorC, 类方法+(void)ClassSelectorC。

现在我们新建一个实例Child* child = [Chlid new];

1,当我们调用[child class] 的时候,child就会通过isa指针去找到Child的class。

2,当我们调用[child superclass]的时候,child 通过isa找到Child的class,再通过super_class,找到Parent的class。

在这里,再普及objc_class 的两种类型:

 class     实例对象(child、Child)的isa指向的结构体;

metaclass  class的isa指向的一个结构体;

3,接着,调用[child SelectorC],child通过isa找到Child的class,在class(注意看上面 struct objc_class 的定义)的方法列表里面找到SelectorC;

4,再试着调用[child SelectorP],child通过isa找到Child的class,发现class里面并没有这个方法,通过class里面的super_class找到Parent的class,在里面的方法列表找到了SelectorP;

5,再是类方法[Child ClassSelectorC],Child(请注意,大写)通过isa找到Child的class,通过class的isa找到Child的metaclass,在metaclass的方法列表里面找到了ClassSelectorC;

6,再试着调用[Child ClassSelectorP],Child通过isa找到Child的class,通过class的isa找到Child的metaclass,发现metaclass里面并没有这个方法,通过metaclass里面的super_class找到Parent的metaclass,在里面的方法列表找到了ClassSelectorP;   

 

 

- (void)viewDidLoad {

    [super viewDidLoad];

    Class clazz = [self class];

    Class clarr = [AroundMapController class];

    Class metalclazz = objc_getMetaClass("AroundMapController");

    if (class_respondsToSelector(metalclazz, @selector(viewWillAppear:))) {

        NSLog(@"ok");

    }

    if (clarr == clazz) {

        NSLog(@"2 ok");

    }

}

这个是验证runtime的机制,可以把这段代码复制到自己的controller.m里面,运行一下。记得把AroundMapController改成自己的controller的名字,还有引入头文件<objc/runtime.h>

 

 

这是几个例子基本上已经涵盖了大多数调用的情况。

细心的朋友可能已经发现,上面的例子中,child通过isa找到的类对象,其实就是Child 通过isa找到的class。(如果能理解这一点,基本上也算对objectC的isa机制也算入门)

 

最后为了理解class和metaclass的作用,大家可以换位思考一下,如果我们作为runtime的设计者,当开发者新建出来一个实例对象child的时候,我们应该存储child的属性和方法,同时又该如何响应其方法调用,最后还要记录与Parent之间的继承关系。

这时候,再来看看,这种图。可以加深对isa机制的理解:

 

 

参考

http://www.cocoachina.com/ios/20141018/9960.html

http://blog.csdn.net/jasonblog/article/details/7246822

http://blog.csdn.net/totogo2010/article/details/8081253

 

0 0