oc 元类 元数据

首先认清一些概念。


struct objc_object {
    Class isa;
};
typedef struct objc_object *id;

struct objc_class {
    Class isa;
    Class super_class;
    const char *name;
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;
    struct objc_method_list **methodLists;
    struct objc_cache *cache;
    struct objc_protocol_list *protocols;
};
typedef struct objc_class *Class;

此结构体可以储存类的诸多信息,例如类型名、父类类型、实例变量列表、方法列表等,这些信息被称作类的元数据(metadata)。该结构体也有一个Class类型的成员isa,说明Class本身也是一个OC对象(被称为类对象或类型对象),而它的对象类型(isa所指向的类型)被称为元类(metaclass),元类中储存的是类对象的元数据,比如类方法就储存在这里。每个类可以有无数个对象,但仅有一个类对象,也仅有一个与之对应的元类。


object_getClass(obj)与[obj class]区别?

object_getClass(obj)返回的是obj中的isa指针;而[obj class]则分两种情况:一是当obj为实例对象时,[obj class]中class是实例方法:- (Class)class,返回的obj对象中的isa指针;二是当obj为类对象(包括元类和根类以及根元类)时,调用的是类方法:+ (Class)class,返回的结果为其本身。

    Class f = object_getClass([sunClass superclass]);

    Class g = object_getClass([[sunClass superclass] class]);

  f == g




Object-C的对象模型图

    metaSunClass * sunClass = [[metaSunClass alloc] init];
   
    Class a = object_getClass(object_getClass([sunClass class]));
    
    Class b = object_getClass(object_getClass([[sunClass superclass] class]));
//此时 a == b 证明上图最右侧虚线元类的class是root[既:NSObject]。

下面的测试代码,是用来获取实例对象的方法和相应的元类方法,证明上图流程。


@interface metaBaseClass : NSObject {
    NSInteger iNum;
}
@property (assign, nonatomic, readonly ) NSInteger uNum;
- (NSInteger) getINumber;
- (void) setINumber:(NSInteger) num;

+ (void)printILog;
+ (void)printIILog;
@end



@implementation metaBaseClass
- (NSInteger) getINumber {
    return iNum;
}
- (void) setINumber:(NSInteger) num {
    iNum = num;
}
+ (void)printILog {
    NSLog(@"show log");
}
+ (void)printIILog {
    NSLog(@"show II log");
}
@end

@interface metaSunClass : metaBaseClass {
    NSInteger yNum;
}
@property (assign, nonatomic, readonly ) NSInteger uYNum;
- (NSInteger) getYNumber;
- (void) setYNumber:(NSInteger) num;

+ (void)printYLog;
@end



@implementation metaSunClass
- (NSInteger) getYNumber {
    return yNum;
}
- (void) setYNumber:(NSInteger) num {
    yNum = num;
}

+ (void)printILog {
    NSLog(@"show Y log");
}


+ (void)printYLog {
    NSLog(@"show YY log");
}
@end


    Method * mm = class_copyMethodList([sunClass class], &count);
    NSLog(@"%u",count);
    for(int j  =0; j < count; j++) {
        Method mt = mm[j];
        SEL sel =method_getName(mt);
        NSString *strName = [NSString stringWithCString:sel_getName(sel)encoding:NSUTF8StringEncoding];
        NSLog(@"%@",strName);
    }


 

打印结果如下:

2016-05-16 20:17:03.698 test[17841:1055828] 3

2016-05-16 20:17:03.698 test[17841:1055828] getYNumber

2016-05-16 20:17:03.699 test[17841:1055828] setYNumber:

2016-05-16 20:17:03.699 test[17841:1055828] uYNum

    Method * mm = class_copyMethodList([[sunClass superclass] class], &count);
    NSLog(@"%u",count);
    for(int j  =0; j < count; j++) {
        Method mt = mm[j];
        SEL sel =method_getName(mt);
        NSString *strName = [NSString stringWithCString:sel_getName(sel)encoding:NSUTF8StringEncoding];
        NSLog(@"%@",strName);
    }

2016-05-16 20:17:49.717 test[17863:1056796] 3

2016-05-16 20:17:49.717 test[17863:1056796] getINumber

2016-05-16 20:17:49.717 test[17863:1056796] setINumber:

2016-05-16 20:17:49.717 test[17863:1056796] uNum

    Method * mm = class_copyMethodList(object_getClass([sunClassclass]), &count);
    NSLog(@"%u",count);
    for(int j  =0; j < count; j++) {
        Method mt = mm[j];
        SEL sel =method_getName(mt);
        NSString *strName = [NSString stringWithCString:sel_getName(sel)encoding:NSUTF8StringEncoding];
        NSLog(@"%@",strName);
    }

2016-05-16 20:19:21.936 test[17888:1058041] 2

2016-05-16 20:19:21.936 test[17888:1058041] printILog

2016-05-16 20:19:21.936 test[17888:1058041] printYLog


    Method * mm = class_copyMethodList(object_getClass([[sunClasssuperclass]class]), &count);
   //equal to  Method * mm = class_copyMethodList(object_getClass([[sunClassclass]superclass]), &count);

    NSLog(@"%u",count);
    for(int j  =0; j < count; j++) {
        Method mt = mm[j];
        SEL sel =method_getName(mt);
        NSString *strName = [NSString stringWithCString:sel_getName(sel)encoding:NSUTF8StringEncoding];
        NSLog(@"%@",strName);
    }


2016-05-16 20:22:32.720 test[17930:1060301] 2

2016-05-16 20:22:32.720 test[17930:1060301] printILog

2016-05-16 20:22:32.720 test[17930:1060301] printIILog



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值