runtime——Class——数据成员

Ivar

struct objc_ivar {
    char *ivar_name                                          OBJC2_UNAVAILABLE;
    char *ivar_type                                          OBJC2_UNAVAILABLE;
    int ivar_offset                                          OBJC2_UNAVAILABLE;
#ifdef __LP64__
    int space                                                OBJC2_UNAVAILABLE;
#endif
}                                                            OBJC2_UNAVAILABLE;

/// An opaque type that represents an instance variable.
typedef struct objc_ivar *Ivar;
OBJC_EXPORT const char *ivar_getName(Ivar v) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
OBJC_EXPORT const char *ivar_getTypeEncoding(Ivar v) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
OBJC_EXPORT ptrdiff_t ivar_getOffset(Ivar v) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);

Ivar应用

@interface FBAnimal : NSObject
{
    int _age;
    UIColor *_color;
}

@end

@implementation FBAnimal

@end
- (void)use_Ivar
{
    Ivar age = class_getInstanceVariable([FBAnimal class], "_age");
    Ivar color = class_getInstanceVariable([FBAnimal class], "_color");
    
    NSLog(@"ivarName = %s, ivarType = %s, ivarOffset = %ld", ivar_getName(age), ivar_getTypeEncoding(age), ivar_getOffset(age));
    NSLog(@"ivarName = %s, ivarType = %s, ivarOffset = %ld", ivar_getName(color), ivar_getTypeEncoding(color), ivar_getOffset(color));
}
output:
ivarName = _age, ivarType = i, ivarOffset = 8
ivarName = _color, ivarType = @"UIColor", ivarOffset = 16

Ivar总结

  • ivar_name:数据成员name
  • ivar_type:数据成员类型
  • ivar_offset:数据成员相对于实例对象首地址offset

api

struct objc_ivar_list {
    int ivar_count                                           OBJC2_UNAVAILABLE;
#ifdef __LP64__
    int space                                                OBJC2_UNAVAILABLE;
#endif
    /* variable length structure */
    struct objc_ivar ivar_list[1]                            OBJC2_UNAVAILABLE;
}                                                            OBJC2_UNAVAILABLE;

long instance_size                                       OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
OBJC_EXPORT BOOL class_addIvar(Class cls, const char *name, size_t size, 
                               uint8_t alignment, const char *types) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
OBJC_EXPORT size_t class_getInstanceSize(Class cls) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
OBJC_EXPORT Ivar class_getInstanceVariable(Class cls, const char *name)
    __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
OBJC_EXPORT Ivar class_getClassVariable(Class cls, const char *name) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
OBJC_EXPORT Ivar *class_copyIvarList(Class cls, unsigned int *outCount) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
OBJC_EXPORT const uint8_t *class_getIvarLayout(Class cls)
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
OBJC_EXPORT void class_setIvarLayout(Class cls, const uint8_t *layout)
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
OBJC_EXPORT const uint8_t *class_getWeakIvarLayout(Class cls)
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
OBJC_EXPORT void class_setWeakIvarLayout(Class cls, const uint8_t *layout)
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);

应用

@interface FBAnimal : NSObject
{
    int _food1;
    int _food2;
}

@end

@interface FBAnimal ()
{
    int _food3;
    int _food4;
}

@end

@interface FBAnimal ()
{
    int _food5;
    int _food6;
}

@end

@implementation FBAnimal
{
    int _food7;
    int _food8;
}

@end

@interface FBDog : FBAnimal
{
    int _age;
    int _color;
}

@end

@implementation FBDog

@end
- (void)class_ivars
{
    NSLog(@"FBAnimal instance size = %lu", class_getInstanceSize([FBAnimal class]));
    NSLog(@"FBDog instance size = %lu", class_getInstanceSize([FBDog class]));
    
    NSLog(@"instance variable");
    Ivar dogVar = class_getInstanceVariable([FBDog class], "_food1");
    NSLog(@"ivarName = %s, ivarType = %s, ivarOffset = %ld", ivar_getName(dogVar), ivar_getTypeEncoding(dogVar), ivar_getOffset(dogVar));
    
    NSLog(@"animal ivar list:");
    unsigned int animalIvarCnt = 0;
    Ivar* animalIvarList = class_copyIvarList([FBAnimal class], &animalIvarCnt);
    for(int i = 0; i < animalIvarCnt; ++i)
    {
        Ivar thisIvar = animalIvarList[i];
        NSLog(@"ivarName = %s, ivarType = %s, ivarOffset = %ld", ivar_getName(thisIvar), ivar_getTypeEncoding(thisIvar), ivar_getOffset(thisIvar));
    }
    free(animalIvarList);
    
    NSLog(@"dog ivar list:");
    unsigned int dogIvarCnt = 0;
    Ivar* dogIvarList = class_copyIvarList([FBDog class], &dogIvarCnt);
    for(int i = 0; i < dogIvarCnt; ++i)
    {
        Ivar thisIvar = dogIvarList[i];
        NSLog(@"ivarName = %s, ivarType = %s, ivarOffset = %ld", ivar_getName(thisIvar), ivar_getTypeEncoding(thisIvar), ivar_getOffset(thisIvar));
    }
    free(dogIvarList);
}
output:
FBAnimal instance size = 40
FBDog instance size = 48
instance variable
ivarName = _food1, ivarType = i, ivarOffset = 8
animal ivar list:
ivarName = _food1, ivarType = i, ivarOffset = 8
ivarName = _food2, ivarType = i, ivarOffset = 12
ivarName = _food5, ivarType = i, ivarOffset = 16
ivarName = _food6, ivarType = i, ivarOffset = 20
ivarName = _food3, ivarType = i, ivarOffset = 24
ivarName = _food4, ivarType = i, ivarOffset = 28
ivarName = _food7, ivarType = i, ivarOffset = 32
ivarName = _food8, ivarType = i, ivarOffset = 36
dog ivar list:
ivarName = _age, ivarType = i, ivarOffset = 40
ivarName = _color, ivarType = i, ivarOffset = 44

总结

  • class_addIvar不支持对已存在class object add,不支持对meta-class object add,只能对objc_allocateClassPair和objc_registerClassPair之间新创建class object add
  • class_getInstanceSize同sizeof(c struct)考虑数据成员内存对齐
  • class_getInstanceVariable(class object)和class_getClassVariable(meta-class object)包含super_class
  • class_copyIvarList不包含super_class
  • _food1 offset为8是因为FBAnimal从NSObject继承了Class isa(指针类型,字长为8,offset为0)
  • 继承体系数据成员offset排列顺序:父类->子类
  • 同一类数据成员offset排列顺序:primary class interface->extension interface->primary class implementation的隐式extension interface
  • 同一类多个extension数据成员offset排列顺序:按extension interface定义顺序逆序排列,即先定义extension interface排后面,后定义extension interface排前面
  • 同一interface(primary class interface,extension interface,primary class implementation的隐式extension interface)数据成员offset排列顺序:按数据成员定义顺序排列,即先定义数据成员排前面,后定义数据成员排后面
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值