美文网首页
RunTime第二篇-类的操作

RunTime第二篇-类的操作

作者: lzh_coder | 来源:发表于2017-09-16 11:59 被阅读2次

接着第一篇介绍了Objective-C中的重要概念的内存模型,这一篇就来熟悉对内存模型的读写操作。

Class操作

Class的操作就是围绕Class的内存模型进行的读写操作,参考上一篇内存模型。

1,获取类名字符串

const char * class_getName ( Class cls );

nil是一个对象值,如果要把一个对象设置为空的时候就用nil。Nil是一个类对象的值,如果要把一个Class类型的对象设置为空的时候就用Nil。NULL是一个通用指针

2,获取Class的父类

Class class_getSuperclass ( Class cls ); //NSObject的superClass是nil;

3,判断一个类是否是一个元类

BOOL class_isMetaClass ( Class cls );//NSObject及其子类的metaClass的metaClass都指向NSObject的metaClass,NSObject的metaClass的superClass指向NSObject,而NSObject的superClass是Nil。

4,获取类的实例的内存size。

size_t class_getInstanceSize ( Class cls );//MBP上,demo类没有任何属性时size为8,添加一个属性size增加8;

5,成员变量操作

Class中的成员变量是用数组存储的。好处是读写快。

struct objc_ivar_list *ivars;

5.1 获取一个成员变量IVar , 会向父类查询。

Ivar class_getInstanceVariable ( Class cls, const char *name );

5.2  获取类成员变量的信息

Ivar class_getClassVariable ( Class cls, const char *name );

5.3 增加一个成员变量只用于动态生成的类已有的类不能通过这个方式增加成员变量。需要注意的是,这个方法只能在objc_allocateClassPair函数与objc_registerClassPair之间调用。成员变量的按字节最小对齐量是1<<alignment,如果变量的类型是指针类型,则传递log2(sizeof(pointer_type))

BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types );

eg.

BOOL  isC = class_addIvar(TestVar,"name6",sizeof(NSString*),log2(sizeof(NSString*)),@encode(NSString*)); //recommend.

BOOL isC = class_addIvar(TestVar,"name7",sizeof(NSString*),log2(_Alignof(NSString*)),@encode(NSString*));//

5.4 获取当前Class的成员变量列表,不包含父类的。

Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );

6 属性操作

属性和成员变量的操作是分开的,但是属性和成员变量存储在同一块数组里面,就是Class里面的struct objc_ivar_list * ivars。

6.1 获取指定属性,会向父类查询。

objc_property_t class_getProperty ( Class cls, const char *name );

6.2 获取属性列表

objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount );

6.3 给类添加属性。属性添加依然要放在动态生成的类中,参考添加变量的方法。5.3

BOOL class_addProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );

6.4 替换类的属性

void class_replaceProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );

7 方法操作

在Class的内存模型里面,方法列表存储在一个链表中,这是因为runtime支持在运行时为已有类和动态生成的类,添加方法,用链表而不用数组来存储,很好地满足这个需求。

7.1 给类添加一个方法。

BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types );

给meta class添加的是类方法,给普通类添加的是实例方法。

往metaClass里面增加的Method,既可以通过class_getInstanceMethod取到,也可以通过class_getClassMethod取到,但是调用只能是类对象Class对象能调用。这个情况,在非metaClass里面不行,非metaClass里面instanceMethod和classMethod互补侵犯。

7.2 获取所有方法的数组

Method * class_copyMethodList ( Class cls, unsigned int *outCount );//对于非metaClass而言,这里不包含类方法,类方法在metaClass里面。

7.3 获取实例方法。

Method class_getInstanceMethod ( Class cls, SEL name ); //注意runtime官方是通过selector来定位一个方法,而不是方法名。前面说过,方法名和selector之间有对应关系。

7.4 获取类方法

Method class_getClassMethod ( Class cls, SEL name );

7.5 替换方法的具体实现

IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types );

注意点:如果已经有这个SEL,那么就更新这个SEL的IMP,如果没有这个SEL,那么相当于class_addMethod..

7.6 获取一个方法的具体实现

IMP class_getMethodImplementation ( Class cls, SEL name );//注意:非metaClass里面,类方法获取不到。这个方法会搜索父类。

如果找到了,返回的IMP的描述如下:

Printing description of imp1:

(IMP) imp1 = 0x0000000100001940 (MyCommandLineDemo`-[MethodOperationSuper methodOperationSuperTest] at MethodOperationSuper.m:13)

如果找不到,会返回消息转发的IMP

Printing description of imp1:

(IMP) imp1 = 0x00007fffdc31dcc0 (libobjc.A.dylib`_objc_msgForward)

7.7 判断一个Class是否能够响应一个selector

BOOL class_respondsToSelector ( Class cls, SEL sel );//注意,这个方法会搜索父类,非metaClass找不到类方法。

8 协议操作

8.1 给类增加一个协议。

BOOL class_addProtocol ( Class cls, Protocol *protocol );

8.2 检查一个类是否遵守了一个协议

BOOL class_conformsToProtocol ( Class cls, Protocol *protocol );

8.3 返回类实现的协议列表

Protocol * class_copyProtocolList ( Class cls, unsigned int *outCount );//注意,该方法不去查询父类遵守的协议。

9.动态创建类

runtime可以在运行期间,动态创建一个类。需要以下流程:

//1.创建一个类,指定父类,类名。

Class objc_allocateClassPair ( Class superclass, const char *name, size_t extraBytes );//extraBytes这个字段一般不需要,设为0;

//2.往类里面填东西,变量,方法。

class_addIvar..

class_addProperty..

class_addMethod..

//3.注册创建好的类。

void objc_registerClassPair ( Class cls );

//4.也可以动态的销毁一个类。

void objc_disposeClassPair ( Class cls );//需要注意的是,如果程序运行中还存在类或其子类的实例,则不能调用针对类调用该方法

9.动态创建类

1.获取注册类列表的数量

int objc_getClassList ( Class *buffer, int bufferCount );//buffer是一个类指针。

//eg.

int numClasses;

Class * classes = NULL;

numClasses = objc_getClassList(NULL, 0);

if (numClasses > 0) {

    classes = malloc(sizeof(Class) * numClasses);

    numClasses = objc_getClassList(classes, numClasses);

    NSLog(@"number of classes: %d", numClasses);

    for (int i = 0; i < numClasses; i++) {

       Class cls = classes[i];

       NSLog(@"class name: %s", class_getName(cls));

     }

      free(classes);

}

2.获取注册类列表的指针

Class * objc_copyClassList ( unsigned int *outCount ); 

相关文章

  • RunTime第二篇-类的操作

    接着第一篇介绍了Objective-C中的重要概念的内存模型,这一篇就来熟悉对内存模型的读写操作。 Class操作...

  • Runtime初识

    runtime的使用先导入runtime类 runtime 可以对类操作举个例子先创建一个Person类在.h中声...

  • Runtime系列 2 -- 成员变量与属性

    本篇为 Runtime 系列文章的第二篇, 其他文章的传送门见下方: Runtime系列 1 -- 类与对象...

  • Runtime系列 4 -- Method Swizzling

    本篇为 Runtime 系列文章的第二篇, 其他文章的传送门见下方: Runtime系列 1 -- 类与对象:传送...

  • 运行时简单介绍

    runtime : runtime:运行时,操作类的函数是以class_开头,操作成员变量的函数以ivar_开头。...

  • Runtime使用

    类与对象操作函数 runtime有很多的函数可以操作类和对象。类相关的是class为前缀,对象相关操作是objc或...

  • Runtime函数库中关于 Class 的函数使用

    Runtime 函数库提供了很多函数用于一些操作,本篇主要总结关于类 Class 的操作函数: 1、根据类名获取类...

  • runtime与model

    使用runtime进行model进行简单操作Model 根类 测试对象Person Man Society 进行字...

  • Object Runtime

    Object Runtime 执行操作 执行结果: 在没有对类做任何操作的情况下,+load 方法会被默认执行,并...

  • 每日一问09——runtime类的操作

    上一章中主要写到runtime中类的实现,这一章我想主要写一下关于runtime中类的一些相关操作。 一、成员变量...

网友评论

      本文标题:RunTime第二篇-类的操作

      本文链接:https://www.haomeiwen.com/subject/gmmysxtx.html