iOS中成员变量的内存偏移量(ivar_offset)研究

在学习Runtime的过程中,自己对objc_ivar中ivar_offset的作用不太理解,所以自己建立了一个工程来研究理解。ivar_offset是指内存偏移量,即该成员变量对于该对象的内存地址偏移了多少,setter和getter方法均会根据此地址来改变该成员属性,那么如果是继承自一个父类,该成员变量的地址又会有什么变化呢?

我们新建两个类,father和son,father继承自NSObject,son继承自father。

1.先让son有一个数组属性,叫做girls:
#import "Father.h"

@interface Son : Father

@property (nonatomic, strong) NSArray *girls;

@end
2.然后我们利用Runtime技术打印该变量的偏移量:
#import "ViewController.h"
#import 
#import "Son.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
     Ivar var_instance_girls = class_getInstanceVariable([Son class], "_girls");
    ptrdiff_t offset_var_girls = ivar_getOffset(var_instance_girls);

    NSLog(@"Grils Offset:%td", offset_var_girls);
}

控制台的结果如下:

Grils Offset:8

偏移结果为8,正对应64-bit系统下一个对象指针为8字节。

3.然后我们给son添加另外一个数组属性叫做cars,然后打印cars的offset:

son:

#import "Father.h"

@interface Son : Father

@property (nonatomic, strong) NSArray *girls;
@property (nonatomic, strong) NSArray *cars;

@end

viewcontroller:

#import "ViewController.h"
#import 
#import "Son.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    Ivar var_instance_girls = class_getInstanceVariable([Son class], "_girls");
    ptrdiff_t offset_var_girls = ivar_getOffset(var_instance_girls);
    NSLog(@"Grils Offset:%td", offset_var_girls);

    Ivar var_instance_cars = class_getInstanceVariable([Son class], "_cars");
    ptrdiff_t offset_var_cars = ivar_getOffset(var_instance_cars);
    NSLog(@"Cars Offset:%td", offset_var_cars);
}

@end

此时,打印结果如下:

Grils Offset:8
Cars Offset:16

这说明新增的成员变量又偏移了一个成员指针的大小,放在前一个成员变量的后面。那么假如father类新增一个成员变量,那么son的成员变量的offset会发生什么变化呢?

4.我们给father增加一个成员变量叫做money:
#import 

@interface Father : NSObject

@property (nonatomic, strong) NSArray *money;

@end

然后打印son的money属性的offset:

#import "ViewController.h"
#import 
#import "Son.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    Ivar var_instance_girls = class_getInstanceVariable([Son class], "_girls");
    ptrdiff_t offset_var_girls = ivar_getOffset(var_instance_girls);
    NSLog(@"Grils Offset:%td", offset_var_girls);

    Ivar var_instance_cars = class_getInstanceVariable([Son class], "_cars");
    ptrdiff_t offset_var_cars = ivar_getOffset(var_instance_cars);
    NSLog(@"Cars Offset:%td", offset_var_cars);
    
    Ivar var_instance_money = class_getInstanceVariable([Son class], "_money");
    ptrdiff_t offset_var_money = ivar_getOffset(var_instance_money);
    NSLog(@"Money Offset:%td", offset_var_money);
}

@end

此时,打印结果如下:

Grils Offset:16
Cars Offset:24
Money Offset:8

我们发现,father新添的成员变量money被排在了第一个位置,而son中的成员变量grils和cars均被向后偏移了。而这正是继承关系应该有的情况。子类继承父类,当然是要优先将父类的成员变量放到前面,然后再添加子类的,这样层层继承下去仅需根据offset的值就能直接使用父类或自己的成员变量了。

你可能感兴趣的:(iOS中成员变量的内存偏移量(ivar_offset)研究)