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];
}