-
平时编写的Objective-C代码,底层转换成C\C++代码,所以OC的面向对象都是基于C\C++的数据结构实现的
OC底层转化过程.png
Objective-C的对象、类主要是基于C\C++的什么数据结构实现的?
结构体
将Objective-C代码转换为C\C++代码?
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件
如果需要链接其他框架,使用-framework参数。比如-framework UIKit
查看内存数据
Debug -> Debug Workfllow -> View Memory (Shift + Command + M

常用LLDB指令
print、p:打印
po:打印对象
读取内存
memory read/数量格式字节数 内存地址
x/数量格式字节数 内存地址
x/3xw 0x10010
格式
x是16进制,f是浮点,d是10进制
字节大小
b:byte 1字节,h:half word 2字节
w:word 4字节,g:giant word 8字节
修改内存中的值
memory write 内存地址 数值
memory write 0x0000010 10
一个NSObject对象占用多少内存?
系统分配了16个字节给NSObject对象(通过malloc_size函数获得)
但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得


底层源码验证
int main(int argc, const char * argv[]) {
@autoreleasepool {
/** class_getInstanceSize 底层代码实现
size_t class_getInstanceSize(Class cls)
{
if (!cls) return 0;
return cls->alignedInstanceSize();
}
// Class's ivar size rounded up to a pointer-size boundary.
uint32_t alignedInstanceSize() {
return word_align(unalignedInstanceSize());
}
//alloc 底层源码分配内存实现
size_t instanceSize(size_t extraBytes) {
size_t size = alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16 bytes.
if (size < 16) size = 16;
return size;
}
*/
NSObject *objc = [[NSObject alloc] init];
// 获得NSObject实例对象的成员变量所占用的大小 -> 8
NSLog(@"%zd",class_getInstanceSize([NSObject class]));
// 获得obj指针所指向内存的大小 -> 16
NSLog(@"%zd",malloc_size((__bridge const void*)objc));
}
return 0;
}
/** 内存中的表现
struct NSObject_IMPL {
Class isa;
};
struct TGPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;//8
int _age;//4
int _height;//4
int _no;//4
}; // 计算结构体内存对齐:内存大小是最大成员变量的倍数,24
*/
@interface TGPerson : NSObject
{
int _age;
int _height;
int _no;
}
@end
@implementation TGPerson
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
TGPerson *p = [[TGPerson alloc] init];
NSLog(@"%zd %zd",
class_getInstanceSize([TGPerson class]), // 24
malloc_size((__bridge const void *)(p))); // 32
}
return 0;
}



OC对象的本质
- instance对象(实例对象)
instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象
实例对象.png
object1、object2是NSObject的instance对象(实例对象)
它们是不同的两个对象,分别占据着两块不同的内存
instance对象在内存中存储的信息包括
- isa指针
-
其他成员变量
person对象.png



- class对象(类对象)

它们是同一个对象。每个类在内存中有且只有一个class对象
class对象在内存中存储的信息主要包括
- isa指针
- superclass指针
- 类的属性信息(@property)、类的对象方法信息(instance method)
- 类的协议信息(protocol)、类的成员变量信息(ivar)
- meta-class对象(元类对象)
objectMetaClass是NSObject的meta-class对象(元类对象)
meta-class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括- isa指针
- superclass指针
- 类的类方法信息(class method)
判断是否是元类对象
Bool result = class_isMetaClass([NSObject class])
object_getClass
Class object_getClass(id obj)
{
//如果是instance对象返回的是class 对象
//如果是class对象返回的是meta-class对象
//如果是meta-class对象,返回的是NSObject(基类)的meta-class对象
if (obj) return obj->getIsa();
else return Nil;
}
isa

-
instance的isa指向class
当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用 -
class的isa指向meta-class
当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用
对象的isa指针指向哪里?
instance对象的isa指向class对象
class对象的isa指向meta-class对象
meta-class对象的isa指向基类的meta-class对象
OC的类信息存放在哪里?
对象方法、属性、成员变量、协议信息,存放在class对象中
类方法,存放在meta-class对象中
成员变量的具体值,存放在instance对象
superclass(类对象内部指针)

当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用

当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用

instance的isa指向class
class的isa指向meta-class
meta-class的isa指向基类的meta-class
class的superclass指向父类的class
如果没有父类,superclass指针为nil
meta-class的superclass指向父类的meta-class
基类的meta-class的superclass指向基类的class
instance调用对象方法的轨迹
isa找到class,方法不存在,就通过superclass找父类
class调用类方法的轨迹
isa找meta-class,方法不存在,就通过superclass找父类


从64bit开始,isa需要进行一次位运算,才能计算出真实地址
@interface TGPerson : NSObject
@end
@implementation TGPerson
@end
struct tg_objc_class {
Class isa;
Class superclass;
};
int main(int argc, const char * argv[]) {
@autoreleasepool {
// TGPerson实例对象的isa:0x001d8001000014c9
// TGPerson类对象的地址:0x00000001000014c8
// isa & ISA_MASK:0x00000001000014c8 & 0x00007ffffffffff8
TGPerson *person = [[TGPerson alloc] init];
struct tg_objc_class *personClass = (__bridge struct tg_objc_class *)([TGPerson class]);
struct tg_objc_class *studentClass = (__bridge struct tg_objc_class *)([TGStudent class]);
return 0;
}

superclass不需要&掩码


class、meta-class对象的本质结构都是struct objc_class

iOS设备CPU架构
-
模拟器
4s ~ 5: i386
5s ~ 7Plus:x86_64 -
真机设备
armv6: iPhone、iPhone 2、iPhone 3G、iPod Touch(第一代)、iPod Touch(第二代)
armv7: iPhone 3Gs、iPhone 4、iPhone 4s、iPad、iPad 2
armv7s: iPhone 5、iPhone 5c (静态库只要支持了armv7,就可以在armv7s的架构上运行)
arm64: iPhone 5s、iPhone 6、iPhone 6 Plus、iPhone 6s、iPhone 6s Plus、iPad Air、iPad Air2、iPad mini2、iPad mini3
网友评论