property(3) - 属性的底层探究

//Test.h
@interface Test : NSObject
{
    NSArray *_array;
}

@property (nonatomic, assign) NSInteger count;
@property (nonatomic, copy) NSString *name;

@end

//Test.m
@implementation Test

@end

//main.m
Test *t = [[Test alloc] init];

t.count = 1;
t.name = @"hh";
NSLog(@"%ld",t.count);
NSLog(@"%@",t.name);

转换成cpp之后的部分主要代码:
这里写图片描述


讲点1:

typedef struct objc_object Test;    

此处将struct objc_object的名字重命为Test,而struct objc_object为:

struct objc_object 
{
    Class _Nonnull isa __attribute__((deprecated));
};

而struct objc_object只有一个类型为Class的isa指针变量,而Class为:

typedef struct objc_class *Class;

可见Class为struct objc_class *的重命名,而struct objc_class 为:

//runtime中可以找到struct objc_class
struct objc_class 
{  
    Class isa;  
    Class super_class;  
    const charchar *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;     //协议列表

} OBJC2_UNAVAILABLE;  

关于struct class结构体的每个参数的详细介绍可以参考此博客链接,此处不讨论:https://blog.csdn.net/uxyheaven/article/details/38113901

这里知道Test类有着变量列表、方法列表即可等信息即可。


讲点2:

extern "C" unsigned long OBJC_IVAR_$_Test$_count;
extern "C" unsigned long OBJC_IVAR_$_Test$_name;

很明显这里是针对@property定义的count,name的。

这里的两个变量代表着一个偏移量,即这两个实例变量在内存中存储的偏移量,通过这两个值能够在内存中快速定位这两个实例变量的位置。


讲点3:

struct Test_IMPL 
{
    struct NSObject_IMPL NSObject_IVARS;
    NSArray *_array;
    NSInteger _count;     
    NSString *_name;      
    //生成了实例变量_count、_name
    //因为默认调用了@synthesize count = _count
    //默认调用了@synthesize name = _name
    //这里如果我们修改@synthesize x = _x 则会生成相应名称的实例变量_x。
};

这即为Test类的实现。struct NSObject_IMPL为:

struct NSObject_IMPL 
{
    Class isa;    
};

这里的isa明显指向类对象,即Test。所以我们可以拿到方法列表、变量列表等信息。


讲点4:

往Test.h添加:

@property (nonatomic, strong) NSDictionary *dictionary;
@property (nonatomic, unsafe_unretained) NSSet *set;
@property (nonatomic, readonly) NSNumber *number;

转换成cpp后:
这里写图片描述
这里写图片描述


讲点5:

在讲点4的基础上讲解前面说的Test类中有的变量列表、方法列表、之类的信息

struct _ivar_t    //描述每个实例变量
{
    unsigned long int *offset;  // pointer to ivar offset location  偏移量
    const char *name;   //名称
    const char *type;   //类型
    unsigned int alignment;   //对齐方式
    unsigned int  size;   //大小
};

static struct /*_ivar_list_t*/ 
{
    unsigned int entsize;  // sizeof(struct _prop_t)  
    unsigned int count;   //个数
    struct _ivar_t ivar_list[6];   
} _OBJC_$_INSTANCE_VARIABLES_Test __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_ivar_t),
    6,
    {{(unsigned long int *)&OBJC_IVAR_$_Test$_array, "_array", "@\"NSArray\"", 3, 8},
     {(unsigned long int *)&OBJC_IVAR_$_Test$_count, "_count", "q", 3, 8},
     {(unsigned long int *)&OBJC_IVAR_$_Test$_name, "_name", "@\"NSString\"", 3, 8},
     {(unsigned long int *)&OBJC_IVAR_$_Test$_dictionary, "_dictionary", "@\"NSDictionary\"", 3, 8},
     {(unsigned long int *)&OBJC_IVAR_$_Test$_set, "_set", "@\"NSSet\"", 3, 8},
     {(unsigned long int *)&OBJC_IVAR_$_Test$_number, "_number", "@\"NSNumber\"", 3, 8}}
};
struct _objc_method   //描述每一个方法
{
    struct objc_selector * _cmd;  //SEL类型的指针
    const char *method_type;   //方法类型
    void  *_imp;   //方法实现
};

static struct /*_method_list_t*/ {
    unsigned int entsize;  // sizeof(struct _objc_method)
    unsigned int method_count;
    struct _objc_method method_list[9];
} _OBJC_$_INSTANCE_METHODS_Test __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_objc_method),
    9,
    {{(struct objc_selector *)"count", "q16@0:8", (void *)_I_Test_count},
    {(struct objc_selector *)"setCount:", "v24@0:8q16", (void *)_I_Test_setCount_},
    {(struct objc_selector *)"name", "@16@0:8", (void *)_I_Test_name},
    {(struct objc_selector *)"setName:", "v24@0:8@16", (void *)_I_Test_setName_},
    {(struct objc_selector *)"dictionary", "@16@0:8", (void *)_I_Test_dictionary},
    {(struct objc_selector *)"setDictionary:", "v24@0:8@16", (void *)_I_Test_setDictionary_},
    {(struct objc_selector *)"set", "@16@0:8", (void *)_I_Test_set},
    {(struct objc_selector *)"setSet:", "v24@0:8@16", (void *)_I_Test_setSet_},
    {(struct objc_selector *)"number", "@16@0:8", (void *)_I_Test_number}}
};
struct _prop_t 
{
    const char *name;   //属性的名称
    const char *attributes;    //属性值
};

static struct /*_prop_list_t*/ {
    unsigned int entsize;  // sizeof(struct _prop_t)
    unsigned int count_of_properties;
    struct _prop_t prop_list[5];
} _OBJC_$_PROP_LIST_Test __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_prop_t),
    5,
    {{"count","Tq,N,V_count"},   //N代表nonaromic
    {"name","T@\"NSString\",C,N,V_name"},   //C代表copy
    {"dictionary","T@\"NSDictionary\",&,N,V_dictionary"},   //&代表strong
    {"set","T@\"NSSet\",N,V_set"},   //
    {"number","T@\"NSNumber\",R,N,V_number"}}   //R代表readonly
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值