iOS中成員變量的內(nèi)存偏移量(ivar_offset)研究

在學(xué)習(xí)Runtime的過程中,自己對objc_ivar中ivar_offset的作用不太理解,所以自己建立了一個工程來研究理解。ivar_offset是指內(nèi)存偏移量,即該成員變量對于該對象的內(nèi)存地址偏移了多少,setter和getter方法均會根據(jù)此地址來改變該成員屬性,那么如果是繼承自一個父類,該成員變量的地址又會有什么變化呢?

我們新建兩個類,father和son,father繼承自NSObject,son繼承自father。

1.先讓son有一個數(shù)組屬性,叫做girls:
#import "Father.h"

@interface Son : Father

@property (nonatomic, strong) NSArray *girls;

@end
2.然后我們利用Runtime技術(shù)打印該變量的偏移量:
#import "ViewController.h"
#import <objc/message.h>
#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);
}

控制臺的結(jié)果如下:

Grils Offset:8

偏移結(jié)果為8,正對應(yīng)64-bit系統(tǒng)下一個對象指針為8字節(jié)。

3.然后我們給son添加另外一個數(shù)組屬性叫做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 <objc/message.h>
#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

此時,打印結(jié)果如下:

Grils Offset:8
Cars Offset:16

這說明新增的成員變量又偏移了一個成員指針的大小,放在前一個成員變量的后面。那么假如father類新增一個成員變量,那么son的成員變量的offset會發(fā)生什么變化呢?

4.我們給father增加一個成員變量叫做money:
#import <Foundation/Foundation.h>

@interface Father : NSObject

@property (nonatomic, strong) NSArray *money;

@end

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

#import "ViewController.h"
#import <objc/message.h>
#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

此時,打印結(jié)果如下:

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

我們發(fā)現(xiàn),father新添的成員變量money被排在了第一個位置,而son中的成員變量grils和cars均被向后偏移了。而這正是繼承關(guān)系應(yīng)該有的情況。子類繼承父類,當(dāng)然是要優(yōu)先將父類的成員變量放到前面,然后再添加子類的,這樣層層繼承下去僅需根據(jù)offset的值就能直接使用父類或自己的成員變量了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容