OC对象的本质

2019-04-30  本文已影响0人  英雄出少年
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

示意图.png
常用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函数获得

NSObject对象底层实现.png 内存分配.png

底层源码验证

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;
}
内存表现.png 底层分配内存函数.png 操作系统分配内存规则.png

OC对象的本质

object1、object2是NSObject的instance对象(实例对象)
它们是不同的两个对象,分别占据着两块不同的内存

instance对象在内存中存储的信息包括

赋值.png p1对象.png p2对象.png 类对象.png
它们是同一个对象。每个类在内存中有且只有一个class对象

class对象在内存中存储的信息主要包括

判断是否是元类对象
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
isa指向.png
对象的isa指针指向哪里?

instance对象的isa指向class对象
class对象的isa指向meta-class对象
meta-class对象的isa指向基类的meta-class对象

OC的类信息存放在哪里?

对象方法、属性、成员变量、协议信息,存放在class对象中
类方法,存放在meta-class对象中
成员变量的具体值,存放在instance对象

superclass(类对象内部指针)
superclass指针.png

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

meta-class的superclass.png

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

isa、superclass.png
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找父类
&掩码.png 掩码宏.png

从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;
}
屏幕快照 2019-05-05 下午11.20.40.png

superclass不需要&掩码

屏幕快照 2019-05-05 下午11.15.38.png class内部结构.png

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

class内部结构底层源码.png
iOS设备CPU架构
上一篇 下一篇

猜你喜欢

热点阅读