您的位置:首页 > 移动开发 > Objective-C

ios - objectC 的isa 详解

2015-12-27 17:22 706 查看
每个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?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: