iOS 基础概念1
OC对象的本质
NSObject
@interface NSObject {
Class isa ;
}
@end
isa
struct NSObject_IMPL {
Class isa;
};
Class isa; 等价于 struct objc_class *isa;
8字节
NSObject对象的底层就是一个包含了一个指针的结构体,它的大小最小8字节
64位系统讨论
内存大小
class_getInstanceSize
获取一个objc类的实例的实际占用大小,部分属性没有值肯定就没有占用内存了
malloc_size
对象实际分配的空间,内存对齐原则,iOS都是16字节的整数倍
占用8字节的,实际分配16字节,多余8字节用不上。 如果实际占用40字节的,
实际分配内存16*3 = 48
sizeof()
计算对象结构定义上可能需要的大小,单纯定义类型大小的累加,编译时计算。
假如对象没有初始化,那实际占用大小0,但是sizeof可不管
源码定义
:#define NANO_MAX_SIZE 256 /* Buckets sized {16, 32, 48, 64, 80,
96, 112, ...}
NANO最大分配256字节,是源码库里面的其中一种内存分配方法,类似的还有
frozen、legacy、magazine、purgeable
对象种类
instance对象(实例对象)
类对象通过alloc方法创建
包含:isa指针,其他成员变量
class对象(类对象)
用来描述一个instance对象
内部存放
isa指针
superclass指针
类的属性信息(@property)
对象方法信息(instance method)
协议信息(protocol)
成员变量信息(ivar)
一个类的类对象是唯一的,在内存中只存一份
meta-class对象
(元类对象)
作用:用来描述一个class对象
内部存放
isa指针
superclass指针
类方法信息(+ class方法)
元类对象在内存中也是只有一份的
实际也是class生成,只是比类对象少用一些字段
cls 结构
class结构- 旧版
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE;
const char * _Nonnull name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;
struct objc_method_list * _Nullable * _Nullable methodLists
OBJC2_UNAVAILABLE;
struct objc_cache * _Nonnull cache
OBJC2_UNAVAILABLE;
struct objc_protocol_list * _Nullable protocols
OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
class 结构 - 新版
struct objc_class : objc_object { // objc_object 内包含 isa
// Class ISA;
Class superclass;
cache_t cache; // 缓存表
class_data_bits_t bits; // class_rw_t内部用来获取基础信息的标记
class_rw_t *data() { // 方法,属性,协议 ,对象信息 等都整合到此处
return bits.data();
}
//下面是一大堆的方法
...
...
...
}
方法对比
object_getClass
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
此方法返回对象的isa指针
传入instance对象,返回对应的class对象
传入class对象,返回对应的meta-class对象
传入meta-class对象,返回NSObject(基类)的meta-class对象
- (Class)class
[obl class]
返回对应的类对象class
+ (Class)class
[cls class]
返回类对象本身
对象方法查找
本段流程是忽略缓存的情况(第一次查找且没有缓存过),下文会有cache_t 篇
详细解释完整流程
instance 对象
调用当前对象方法
通过isa到对应类对象,在类对象找到对象方法,一般先看缓存
调用父类对象方法
1.通过isa到对应类对象
2.通过类对象supperclass指针 找到父类的类对象,然后在其找对象方法, 找不
到会一层层往上遍历,直到基类
class 类对象
调用当前类的类方法
通过isa找到对应的元类对象,在元类对象找类方法,一般先看缓存
调用父类的类方法
1.通过isa找到对应的元类对象
2.通过元类对象supperclass指针 找到父类的元类对象,然后在其找类方法, 找
不到会一层层往上遍历,直到根类
同样也会先查找缓存,没有的下次会缓存起来
信息存放
1.对象方法,属性信息,成员变量信息,协议信息,存放在class对象中
2.类方法,存放在meta-class对象中
3. 成员变量的具体值,存放在instance对象中