/**
三种层面上与runtime进行交互
*/
/**
1.OC源代码
*/
/** 多数情况我们只需要编写 OC 代码即可,Runtime 系统自动在幕后搞定一切,还记得简介中如果我们调用方法,编译器会将 OC 代码转换成运行时代码,在运行时确定数据结构和函数*/
/**
2.通过 Foundation 框架的 NSObject 类定义的方法
Cocoa 程序中绝大部分类都是 NSObject 类的子类,所以都继承了 NSObject 的行为。(NSProxy 类是个例外,它是个抽象超类)
一些情况下,NSObject 类仅仅定义了完成某件事情的模板,并没有提供所需要的代码。例如 -description 方法,该方法返回类内容的字符串,该方法主要用来调试程序。NSObject 类并不知道子类的内容,所以它只是返回类的名字和对象的地址,NSObject 的子类可以重新实现
还有一些NSObject的方法可以从Runtime系统中获取信息,允许对象进行自我检查。例如:
* -class方法返回对象的类
* -isKindOfClass:和-isMemberOfClass:方法检查对象是否存在于指定的类的继承体系中(是否是其子类或者是父类或者当前类的成员变量)
* -respondsToSelector:检查对象能否响应指定的消息
* -conformsToProtocol:检查对象是否实现了指定的协议类的方法;
* -methodForSelector:返回指定方法实现的地址
*/
/**
3.通过对runtime库函数的直接调用
runtime系统是具有公共接口的动态共享库。头文件存放于 /user/include/objc目录下,这意味着我们使用时只需要引入
*/
}
-
(void)runtimeFountion
{
/**
获取类:
Class personClass = object_getClass([self class]);SEL是selector在Objc中的表示:
SEL oriSel = @selector(text1);获取类方法
Method oriMethod = class_getClassMethod(__unsafe_unretained Class cls, SEL name);获取实例方法
Method origInstance = class_getInstanceMethod(__unsafe_unretained Class cls, SEL name);添加方法
BOOL addSucc = class_addMethod(xiaoming, oriSel, method_getImplementation(Method m), method_getTypeEncoding(Method m))替换原方法
class_replaceMethod(toolClass, cusSel, method_getImplementation(Method m), method_getTypeEncoding(Method m));交换两个方法
method_exchangeImplementations(Method m1, Method m2);获取一个类的属性列表(返回值为一个数组)
objc_property_t *propertyList = class_copyPropertyList([self class], &count);获取一个类的方法列表 (返回值是一个数组)
Method *methodList = class_copyMethodList([self class], &count);获取一个类的成员变量列表(返回值是一个数组)
Iver *ivarList = class_copyIvarList([self class], &count);获取成员变量的名字
const char *ivar_getName(Ivar v);获取成员变量的类型
const char * ivar_getTypeEndcoding(Ivar v);获取一个类的协议列表(返回值是一个数组)
__unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class], &count);set方法
将值value 跟对象object关联起来(将值value存储到对象object中)
参数object:给哪个对象设置属性
参数key :一个属性对应一个key,将来可以通过key取出这个存储的值,key可以是任何类型:建议用char以节省字节
参数value:给属性设置的值
参数policy:存储策略(assign、copy、retain就是strong)objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
利用key将对象object中存储的对应的值取出来
objc_getAssociatedObject(id object, const void *key);*/
}
/**
runtime术语及数据结构
*/
-
(void)dataSel
{
/**
SEL
它是selector在 Objc 中的表示(Swift 中是 Selector 类)。selector 是方法选择器,其实作用就和名字一样,日常生活中,我们通过人名辨别谁是谁,注意 Objc 在相同的类中不会有命名相同的两个方法。selector 对方法名进行包装,以便找到对应的方法实现。它的数据结构是:typedef struct objc_selector *SEL; 我们可以看出它是个映射到方法的C字符串,你可以通过Objc编译器命令@selector()或者runtime系统的sel_registerName函数来获取一个SEL类型的方法选择器 *注意:不同类中相同名字的方法所对应的selector是相同的,由于变量的类型不同,所以不会导致它们调用方法实现混乱。
*/
/**
id
id是一个参数类型,它是指向某个类的实例的指针。定义如下:
typedef struct objc_object *id;
struct objc_object{ Class isa; };
以上定义,看到objc_object结构体包含一个isa指针,根据isa指针就可以找到对象所属的类。
注意:isa指针在代码运行时并不总是指向实例对象所属的类型,所以不能依靠它来确定类型,要想确定类型还是需要用对象的-class方法
PS:KVO 的实现机理就是将被观察对象的isa指针指向一个中间类而不是真实类型。
*/
/**
Class
typedef struct objc_class *class;
Class其实是指向objc_class结构体的指针。objc)_class的数据结构如下:
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
#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
} OBJC2_UNAVAILABLE;
从objc_class 可以看到,一个运行时类中关联了它的父类指针、类名、成员变量、方法、缓存以及附属的协议。
*/
}
网友评论