Working with Classes
方法声明:
const char * class_getName ( Class cls );
描述:获取cls类对象的名称
举例:
NSLog(@"%s", class_getName([Book class]));
打印信息:
2015-09-14 10:52:35.147 AppTest[5839:81954] Book
方法声明:
Class class_getSuperclass ( Class cls );
描述:获取cls类对象的超类
举例:
NSLog(@"%@", class_getSuperclass([Book class]));
打印信息:
2015-09-14 10:55:23.402 AppTest[5958:84223] BaseModel
方法声明:
BOOL class_isMetaClass ( Class cls );
描述:判断cls类对象是否是元类对象
举例:
NSObject *object = [[NSObject alloc] init]; Class class = [NSObject class]; BOOL yup = class_isMetaClass(object_getClass(class)); BOOL nope = class_isMetaClass(object_getClass(object)); NSLog(@"%d,%d", yup,nope);打印信息:
2015-09-14 14:18:43.622 AppTest[9738:145947] 1,0
方法声明:
size_t class_getInstanceSize ( Class cls );
描述:获取cls类对象的实例大小(字节数),我理解是创建一个类的实例所需要的内存大小;
举例:
@interface BaseModel : NSObject { } // Properties @property(copy, nonatomic) NSString *className; // // Methods - (NSString *)jsonValue; - (NSDictionary *)dictionaryValue; - (NSDictionary *)propertyDictionary; - (BOOL)isEqualToModel:(BaseModel *)model; @end
@interface Book : BaseModel { @private NSString* _privateName; } @property (strong, nonatomic) NSString *author; @property (assign, nonatomic) NSUInteger pages; @property (strong, nonatomic) Pen *pen;
@interface Pen : BaseModel @property (strong, nonatomic) NSString *color; @property (assign, nonatomic) int type;
Book *book = [[Book alloc]init]; NSLog(@"%zu", class_getInstanceSize([NSObject class])); NSLog(@"%zu", class_getInstanceSize([BaseModel class])); NSLog(@"%zu", class_getInstanceSize([Book class])); NSLog(@"%zu", class_getInstanceSize([Pen class])); NSLog(@"sizeof myObject: %ld", sizeof(book));打印信息:
2015-09-14 12:08:11.992 AppTest[8644:128563] 8
2015-09-14 12:08:11.993 AppTest[8644:128563] 16
2015-09-14 12:08:11.993 AppTest[8644:128563] 48
2015-09-14 12:08:11.993 AppTest[8644:128563] 32
2015-09-14 12:08:11.993 AppTest[8644:128563] sizeof myObject: 8
说明:从最后一个打印信息可以看出64位下指针大小是8个字节,那么基类NSObject的大小正好是8个字节,因为它的成员变量就一个isa指针;因为方法是所有实例对象共享的,所以不会占用对象的存储空间,BaseModel除了isa新增了className属性,因此是2*8;这里的Book中pen是8,因为它只是一个指针变量;而Pen中type只占4个字节,之所以总共占有是32字节是因为字节对齐的原因;
方法声明:
Ivar class_getInstanceVariable ( Class cls, const char *name );
描述:获取cls类的名称为name的成员变量的详细信息,这个信息返回给Ivar类型的结构体
举例:
Ivar ivar = class_getInstanceVariable([Book class], "_privateName"); NSLog(@"%s,%s,%td", ivar_getName(ivar),ivar_getTypeEncoding(ivar),ivar_getOffset(ivar)); ivar = class_getInstanceVariable([Book class], "_pen"); NSLog(@"%s,%s,%td", ivar_getName(ivar),ivar_getTypeEncoding(ivar),ivar_getOffset(ivar));打印信息:
2015-09-14 17:11:16.668 AppTest[16182:244363] _privateName,@"NSString",16
2015-09-14 17:11:16.669 AppTest[16182:244363] _pen,@"Pen",40
方法声明:
Ivar class_getClassVariable ( Class cls, const char *name );
描述:获取cls类的名称为name的类变量的详细信息,这个信息返回给Ivar类型的结构体
举例:
Ivar ivar = class_getClassVariable([Book class], "isa"); NSLog(@"%s,%s,%td", ivar_getName(ivar),ivar_getTypeEncoding(ivar),ivar_getOffset(ivar));打印信息:
2015-09-14 17:09:27.278 AppTest[16092:242813] isa,#,0
说明:个人理解OC是没有类变量的,这里应该是指的元类对象,元类对象只有一个变量就是isa,可以参考http://stackoverflow.com/questions/1980703/what-does-class-getclassvariable-do理解class_getClassVariable(cls, name) merely calls class_getInstanceVariable(cls->isa, name)
方法声明:
BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char*types );
描述:给一个类添加新的实例变量,成功则返回YES;
这个方法只能在 objc_allocateClassPair
和 objc_registerClassPair
之间调用,而不能给一个已经存在的类添加实例变量;
这个cls不能是元类,给一个元类添加实例变量是不被支持的;
实例变量的最小对齐方式为1。实例变量的最小对齐取决于变量的类型和机器的体系结构。对于任何一种类型的指针变量,通过log2(sizeof(pointer_type))方法得到。
举例:参考动态添加类
方法声明:
Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );
描述:获取类声明的实例变量,返回所有实例变量描述信息的数组的指针,数组的类型是Ivar,这个数组中不包含父类的实例变量,outCount指针返回数组的个数,最后使用完以后要通过free()释放这个数组指针;
举例:
Class cls = [Book class]; unsigned int ivarsCnt = 0; // 获取类成员变量列表,ivarsCnt为类成员数量 Ivar *ivars = class_copyIvarList(cls, &ivarsCnt); // 遍历成员变量列表,其中每个变量都是Ivar类型的结构体 for (const Ivar *p = ivars; p < ivars + ivarsCnt; p++) { Ivar const ivar = *p; NSLog(@"ivar: %@", [NSString stringWithUTF8String:ivar_getName(ivar)]); } free(ivars);
打印信息:
2015-09-15 17:25:03.192 AppTest[17305:227452] ivar: _privateName
2015-09-15 17:27:01.071 AppTest[17305:227452] ivar: _author
2015-09-15 17:27:01.071 AppTest[17305:227452] ivar: _pages
2015-09-15 17:27:01.071 AppTest[17305:227452] ivar: _pen
方法声明:
const uint8_t * class_getIvarLayout ( Class cls );
描述:返回给定类的实例变量布局(这个布局指的是否是强引用)的描述信息
举例:(见下面例子)
方法声明:
void class_setIvarLayout ( Class cls, const uint8_t *layout );
描述:设定给定类的实例变量的布局(这个布局指的是强引用)
举例:(见下面例子)
方法声明:
const uint8_t * class_getWeakIvarLayout ( Class cls );
描述:返回给定类的实例变量布局(这个布局指的是否是弱引用)的描述信息
举例:(见下面例子)
方法声明:
void class_setWeakIvarLayout ( Class cls, const uint8_t *layout );
描述:设定给定类的实例变量的布局(这个布局指的是弱引用)
举例:
@interface Book : BaseModel { @private __strong id ivar0; __weak id ivar1; __strong id ivar2; __weak id ivar3; } @property (strong, nonatomic) NSString *ivar4; @property (weak, nonatomic) NSString *ivar5; @end
Class cls = [Book class]; const uint8_t *ret = class_getIvarLayout(cls); const uint8_t *ret1 = class_getWeakIvarLayout(cls); int i=0; uint8_t value = ret[i]; while (value != 0x0) { printf("\\x%02x",value); value = ret[++i]; } printf("\r\n"); i=0; value = ret1[i]; while (value != 0x0) { printf("\\x%02x",value); value = ret1[++i]; }
\x01\x11\x11\x10
\x11\x11\x11
x11表示1个非strong,1个strong;
x11表示1个非strong,1个strong;
x10表示1个非strong,0个strong;
第二行是弱引用的描述信息,x11表示1个非weak,1个weak;
x11表示1个非weak,1个weak;
x11表示1个非weak,1个weak;
Class cls = [Book class]; unsigned char lay[1] ; lay[0] = 0x15; unsigned char lay1[2] ; lay1[0] = 0x01; lay1[1] = 0x50; class_setIvarLayout ( cls, lay ); class_setWeakIvarLayout(cls, lay1 ); const uint8_t *ret = class_getIvarLayout(cls); const uint8_t *ret1 = class_getWeakIvarLayout(cls); int i=0; uint8_t value = ret[i]; while (value != 0x0) { printf("%02x",value); value = ret[++i]; } printf("\r\n"); i=0; value = ret1[i]; while (value != 0x0) { printf("%02x",value); value = ret1[++i]; }