Objective-C的本質(zhì)
我們平時(shí)編寫的Objective-C代碼八千,底層實(shí)現(xiàn)其實(shí)都是C\C++代碼
image.png
將OC代碼翻譯成C++代碼馍惹,我們可以看到
// NSObject Implementation
struct NSObject_IMPL {
Class isa; // 8個(gè)字節(jié)
};
// 指針
// typedef struct objc_class *Class;
所以O(shè)bjective-C的面向?qū)ο蠖际腔贑\C++的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的
Objective-C的對(duì)象、類主要是基于C\C++的什么數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的龙宏?
答:結(jié)構(gòu)體
- 將Objective-C代碼轉(zhuǎn)換為C\C++代碼
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 輸出的CPP文件
如果需要鏈接其他框架棵逊,使用-framework參數(shù)。比如-framework UIKit
2. 一個(gè)OC對(duì)象在內(nèi)存中是如何布局的银酗?
- NSObject的底層實(shí)現(xiàn)
image.png
- 繼承自NSObject的類的內(nèi)存布局
image.png
image.png
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>
// NSObject Implementation
struct NSObject_IMPL {
Class isa; // 8個(gè)字節(jié)
};
// 指針 - typedef struct objc_class *Class;
struct Student_IMPL {
struct NSObject_IMPL NSObject_IVARS; // 8個(gè)字節(jié)
int _no; // 4
int _age; // 4
}; // 16個(gè)字節(jié),內(nèi)存對(duì)齊,結(jié)構(gòu)體的大小必須是最大成員大小的倍數(shù)
// Person
@interface Student: NSObject {
@public
int _no;
int _age;
}
@end
@implementation Student
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSObject *obj = [[NSObject alloc] init];
// 獲得NSObject實(shí)例對(duì)象的成員變量所占用的大小 >> 8
NSLog(@"%zd",class_getInstanceSize([NSObject class]));
// 獲得obj指針?biāo)赶騼?nèi)存的大小 >> 16
NSLog(@"%zd",malloc_size((__bridge const void *)obj));
Student *stu = [[Student alloc] init];
NSLog(@"stu - %zd",class_getInstanceSize([Student class]));
NSLog(@"stu - %zd",malloc_size((__bridge const void *)stu));
}
return 0;
}
打印結(jié)果
image.png
思考:一個(gè)Person對(duì)象辆影、一個(gè)Student對(duì)象占用多少內(nèi)存空間?
image.png
- 代碼實(shí)現(xiàn)如下
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>
// NSObject Implementation
struct NSObject_IMPL {
Class isa; // 8個(gè)字節(jié)
};
// 指針 - typedef struct objc_class *Class;
struct Person_IMPL {
struct NSObject_IMPL NSObject_IVARS; // 8個(gè)字節(jié)
int _age; // 4
}; // 16個(gè)字節(jié),內(nèi)存對(duì)齊,結(jié)構(gòu)體的大小必須是最大成員大小的倍數(shù)
// Person
@interface Person: NSObject {
int _age;
}
@end
@implementation Person
@end
// Person
@interface Student: Person {
int _no;
}
@end
@implementation Student
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSObject *obj = [[NSObject alloc] init];
// 獲得NSObject實(shí)例對(duì)象的成員變量所占用的大小 >> 8
NSLog(@"%zd",class_getInstanceSize([NSObject class]));
// 獲得obj指針?biāo)赶騼?nèi)存的大小 >> 16
NSLog(@"%zd",malloc_size((__bridge const void *)obj));
Person *person = [[Person alloc] init];
NSLog(@"Person - %zd",class_getInstanceSize([Person class]));
NSLog(@"Person - %zd",malloc_size((__bridge const void *)person));
Student *stu = [[Student alloc] init];
NSLog(@"stu - %zd",class_getInstanceSize([Student class]));
NSLog(@"stu - %zd",malloc_size((__bridge const void *)stu));
}
return 0;
}
運(yùn)行結(jié)果
image.png
2個(gè)容易混淆的函數(shù)
- 創(chuàng)建一個(gè)實(shí)例對(duì)象黍特,至少需要多少內(nèi)存蛙讥?
#import <objc/runtime.h>
class_getInstanceSize([NSObject class]);
- 創(chuàng)建一個(gè)實(shí)例對(duì)象,實(shí)際上分配了多少內(nèi)存灭衷?
#import <malloc/malloc.h>
malloc_size((__bridge const void *)obj);
2.常用LLDB指令
- 打印
print次慢、p:打印
po:打印對(duì)象
- 讀取內(nèi)存
memory read/數(shù)量格式字節(jié)數(shù) 內(nèi)存地址
x/數(shù)量格式字節(jié)數(shù) 內(nèi)存地址
x/3xw 0x10010
- 修改內(nèi)存中的值
memory write 內(nèi)存地址 數(shù)值
memory write 0x0000010 10
- 格式
x是16進(jìn)制,f是浮點(diǎn),d是10進(jìn)制
- 字節(jié)大小
b:byte 1字節(jié)迫像,h:half word 2字節(jié)
w:word 4字節(jié)劈愚,g:giant word 8字節(jié)
本文參考借鑒MJ的教程視頻,非常感謝.