https://justsee.iteye.com/blog/2163905
总结:
1.实例对象 (类对象的实例对象):实例对象是运行的时候生成的,都是在运行时由Objective-C的运行时库生成的。
2.类对象 (元类对象的一个实例)是由编译器创建的。
3.元类对象是根元类对象的一个实例。是由编译器创建的。
1.people为例子, People *people = [[People alloc] init];
编译器会生成 2个对象,people 是类对象object_getClass(people)的实例,object_getClass(people)是元类object_getClass(object_getClass(classPeople))的实例。
2.1.类对象里面有方法 get set 方法,方法--1--classMthod1 属性:year name age
2.元类对象里面有方法 classMthod2 属性:year name age
3.根元类里面有方法 -isEqual: allocWithZone: release respondsToSelector nsobject.h所具有的。
属性:属性名称--3--accessInstanceVariablesDirectly
1.runtime 运行时系统,runtime是由c和汇编写的。
编译器会将OC代码转换成运行时候的代码,在运行时确定数据结构和函数。
编译器和JAVA的比较。NSProxy NSObject?
https://www.jianshu.com/p/d4b55dae9a0d
OC是动态语言,不像C语言一样,编译阶段就要决定调用哪个函数,如果函数未实现就会编译报错,
OC 编译阶段并不能决定真正的调用哪个函数,只要函数声明过即使没有实现不会报错。
我们常说OC是一门动态语言,就是因为它总是把一些决定性的工作从编译阶段推迟到运行时阶段。OC代码的运行不仅需要编译器,还需要运行时系统(Runtime Sytem)来执行编译后的代码。
2.类对象,实例对象,和元类对象。
oc动态性:
1.动态类型:id类型。
2.动态绑定:一般在编译的时候就已经将要调用的函数的函数签名都告诉编译器了。静 态的,不能改变。而在OC中,其实是没有函数的概念的,我们叫“消息机制”,所谓的 函数调用就是给对象发送一条消息。这时,动态绑定的特性就来了。OC可以先跳过编 译,到运行的时候才动态地添加函数调用,在运行时才决定要调用什么方法,需要传 什么参数进去,这就是
3动态加载:动态地加载资源,在运行时加载新类。
1.Rutime消息发送.
1.编译语言与OBJC 运行动态语言的区别是什么?
2.消息传递机制与函数调用区别?
3.消息转发?
4.方法缓存,
1.数据结构,类对象元类对象,消息传递,方法缓存,
消息转发 method-swizzling 方法混淆,运行时候去替换方法。
动态添加方法,动态方法解析
typedef struct objc_object {
Class isa;
} *id;
id—objc_object—isa
—弱引用相关
—关联对象相关
—内存管理相关 retain release pool
**Class = objc_class **
struct objc_class {
Class isa;
if !OBJC2
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
endif
}
https://www.jianshu.com/p/45db86af7b60
指针型:isa的值代表class 的地址。
非指针型isa:isa的值部分代表class的地址。
实例isa——> Class 类对象。——> Class 元类对象。
1.cathe_t 用于快速查找方法执行函数。
2.可增量扩展的哈希表结构。扩大内存空间,为了提高查找效率。
3.局部性原理。调用频率最高的放到缓存表。
数组
**bucket_t bucket_t. bucket_t bucket_t **
Key IMP
class_data_bits_t 对class_rw_t的封装。
class_rw_t代表了类相关的读写信息,对class_ro_t 的封装。
class_ro_t代表了类相关的只读信息。
//二维数组———》分类
typedef struct class_rw_t {
uint32_t flags;
uint32_t version;
const class_ro_t *ro;
method_list_t **methods;
struct chained_property_list *properties;
const protocol_list_t ** protocols;
struct class_t *firstSubclass;
struct class_t *nextSiblingClass;
} class_rw_t;
//一维数组—原始定义的添加的。
typedef struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
ifdef LP64
uint32_t reserved;
endif
const uint8_t * ivarLayout;
const char * name;
const method_list_t * baseMethods;
const protocol_list_t * baseProtocols;
const ivar_list_t * ivars;
const uint8_t * weakIvarLayout;
const property_list_t *baseProperties;
} class_ro_t;
method_t
根类的父类是nil.
1.实例对象,类对象,元类对象,
1.子类元类,父类对象,根类对象都指向根类对象。
**2.objct_getclass **
3.子类元类superclass是父类元类对象superclass是根类元类对象superclass找同名的实例类对象。
2.
super是一个编译器标识符,在运行时中与self相同,指向同一个消息接受者,只是self会优先在当前类的methodLists中查找方法,而super则是优先从父类中查找
objc_msgSend((id)self, sel_registerName("class"));
objc_msgSendSuper((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("JQApple"))}, sel_registerName("class"));
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained id receiver;
/// Specifies the particular superclass of the instance to message.
__unsafe_unretained Class super_class;
/* super_class is the first class to search */
};
我们把self以及JQApple的父类通过结构体的构造方法构造了一个__rw_objc_super结构体,也就是objc_super
因此objc_super结构体中的receiver既是self。所以[self class]和[super class]指向的是同一个消息接受者,
3.消息传递:
self class objc_msgsend (id self,SEL op)编译器层
objc_msgSend((id)self, sel_registerName("class"));
objc_msgSendSuper((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("JQApple"))}, sel_registerName("class"));
class_getSuperclass
__rw_objc_super
对象方法
首先查缓存列表—isa—当前类对象方法列表—super—父类缓存/方法列表——nsobject根—nil
类方法
首先查缓存列表—isa—isa—元类对象类方法列表—super—父类缓存类方法列表——根元类—-同名实例对xiang
4.缓存查找 ——》哈希算法。———》扩展
缓存查找:SEL
hash算出的值
key & mask = f(key)
目标值是bucket_t中的IMP.哈希查找,根据f(key) 查找出bucket_t.提取对应的imp.
5.当前类中的查找—————》二分查找———》扩展
已经排序好的列表,采用二分查找算法查找方法对应执行函数。
没有排序的列表,采用一般遍历查找方法对应执行函数。
6.父类逐级查找
先检查父类缓存—>superclass 方法列表—>然后父类缓存—>方法列表。
7.消息转发流程:
+resolveInstanceMethod: 或 +resolveClassMethod:
证书,签名等等。。。
跨平台。
1.动态方法解析。
resolveinstancemthod.
2.快速消息转发。
forwardTargetforselctor
3.标准消息转发。
methodSignatureForSelector:
forwardInvocation:
v void类型, @代表第一个参数类型id self :代表第二个参数是SEL类型的。
4.runtime的应用:
1.runtime交换方法:
2.动态添加方法:
[图片上传中...(Xnip2019-04-17_15-49-11.jpg-3613fc-1555498321835-0)]
3.分类添加属性:
4.KVO实现———》扩展
KVO实现
KVO的实现依赖于 Objective-C 强大的 Runtime,当观察某对象 A 时,KVO 机制动态创建一个对象A当前类的子类,并为这个新的子类重写了被观察属性 keyPath 的 setter 方法。setter 方法随后负责通知观察对象属性的改变状况。
5.实现NSCoding的自动归档和自动解档
6.load方法:
oc中 +load方法的深层理解
https://blog.csdn.net/wei371522/article/details/81211346
- load 作为 Objective-C 中的一个方法,与其它方法有很大的不同。它只是一个在整个文件被加载到运行时,在 main 函数调用之前被 ObjC 运行时调用的钩子方法。其中关键字有这么几个:
文件刚加载
main 函数之前
钩子方法