• ios


    每个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

    --问答题---

    如果给你一个child的实例对象,要如何才能访问到它的父类的静态方法ClassSelectorP?

  • 相关阅读:
    android学习计划
    Android源码下载及开发环境的搭建
    I2C总线时序
    I2C原理和实例
    sql语句获取字段扩展属性
    浏览器兼容:火狐不支持webq格式图片
    js节流函数中的参数传递
    分享插件使用
    图片等比例自适应填充
    window.event在IE和Firefox的异同
  • 原文地址:https://www.cnblogs.com/loying/p/5080429.html
Copyright © 2020-2023  润新知