iOS底层原理

小码哥底层原理笔记:OC对象的分类(一)

2020-04-28  本文已影响0人  chilim

OC的对象分为三类:

实例对象

instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象,每个实例对象的内存地址都不一样

int main(int argc, char * argv[]) {
    @autoreleasepool {
//实例对象
        NSObject *object1 = [[NSObject alloc] init];
        NSObject *object2 = [[NSObject alloc] init];
        //实例对象内存地址打印
        NSLog(@"%p %p",object1,object2);
        //0x28039c180 0x28039c170,内存地址不一样。说明实例对象是不同的
    }
    return 0;
}

instance实例对象只保存成员变量

class类对象

通过class方法或runtime方法得到一个class对象

int main(int argc, char * argv[]) {
    @autoreleasepool {
        //类对象,一个类对象是唯一的,在内存中只有一份
        Class objectClass1 = [object1 class];
        Class objectClass2 = [object2 class];
        Class objectClass3 = [NSObject class];
        
        Class objectClass4 = object_getClass(object1);
        Class objectClass5 = object_getClass(object2);
        //类对象内存地址打印
        NSLog(@"%p %p %p %p %p",
              objectClass1,objectClass2,objectClass3,objectClass4,objectClass5);
        //0x1e3d9beb0 0x1e3d9beb0 0x1e3d9beb0 0x1e3d9beb0 0x1e3d9beb0,内存地址都一样,说明在内存中只有一个类对象
    }
    return 0;
}

可以看到不管用什么方法生成的类对象的内存地址都是一样的,说明每一个类在内存中有且只有一个class对象。
之前提到instance实例对象不保存方法,只保存成员变量。方法保存在class类对象中
类对象中主要包含:

元类对象 meta-class

通过runtime方法object_getClass传入一个类对象得到元类对象

int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSObject *object1 = [[NSObject alloc] init];
        NSObject *object2 = [[NSObject alloc] init];
        //元类对象,将类对象当作参数,获得元类对象,每个类中也只有一个元类对象,在内存是唯一的
        Class objectMetaClass1 = object_getClass([NSObject class]);
        Class objectMetaClass2 = object_getClass([NSObject class]);
        NSLog(@"metaclass - %p %p",objectMetaClass1,objectMetaClass2);
        //0x1e3d9be60 0x1e3d9be60
    }
    return 0;
}

通过打印的内存地址可以知道 每个类中也只有一个元类对象,在内存是唯一的
meta-class元类对象保存的内容与类对象类似,主要是

注:我们知道用class方法可以获得class类对象,但是类对象调用class方法依旧是类对象,而不是元类对象

Class objectClass3 = [NSObject class];//这是一个类对象
Class objectClass2 = [[NSObject class] class];//这是一个类对象,而不是元类对象
NSLog(@"class - %p %p", objectClass3, objectClass2);//class - 0x1e3d9be60,0x1e3d9be60

以上代码可以看到,类对象调用class方法后还是一个类对象,而并不是元类对象,只有通过runtime方法object_getClass传入一个类对象才得到元类对象

总结:每一个类可以有多个实例对象,但是对应只有一个类对象和元类对象。

上一篇 下一篇

猜你喜欢

热点阅读