Runtime核心之-数据结构
每个类的实例变量都有一个Class isa
typedef struct objc_class *Class;
struct objc_class
struct objc_class {
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;
类结构的关联关系(图),runtime的基础
Runtime核心之-消息机制
关键方法:objc_msgSend
参数:id obj(接收者), SEL sel(方法选择器), arg1...(方法参数表)
通过obj->isa 可以遍历类的结构,包括父类。结合sel就可以找到对应的函数指针,结合后面的参数表就可以执行函数了,方法对应的c函数也包含id obj(接收者), SEL sel(方法选择器)这两个参数,编译器自动添加的被称为隐藏参数。oc中可以通过self和_cmd访问到。
Runtime-NSObject常用方法
/*一般方法*/
- (Class)class; // 获取对象类型
- (BOOL)isKindOfClass:(Class)aClass; // 是否是类或者其子类的实例
- (BOOL)isMemberOfClass:(Class)aClass; // 是否当前类的实例
- (BOOL)conformsToProtocol:(Protocol *)aProtocol; // 对象是否实现了Protocol
- (BOOL)respondsToSelector:(SEL)aSelector; // 对象是否实现了方法
/*动态解析相关方法*/
+ (BOOL)resolveInstanceMethod:(SEL)sel;
+ (BOOL)resolveClassMethod:(SEL)sel;
/*消息转发相关方法*/
- (id)forwardingTargetForSelector:(SEL)aSelector;
- (void)forwardInvocation:(NSInvocation *)anInvocation;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
conformsToProtocol 使用demo
ClassA *a = [ClassA new];
NSLog(@"%d", [a conformsToProtocol:@protocol(MyProtocolName)]); //1
Runtime-runtime常用源码方法
/*访问成员变量方法*/
Ivar * class_copyIvarList(Class cls, unsigned int *outCount)
objc_property_t * class_copyPropertyList(Class cls, unsigned int *outCount);
/*动态方法处理相关方法*/
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);
IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types);
IMP method_getImplementation(Method m);
IMP method_setImplementation(Method m, IMP imp);
void method_exchangeImplementations(Method m1, Method m2);
Runtime-应用
方法动态解析
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSString *selName = NSStringFromSelector(sel);
if ([selName isEqualToString:@"nihao"]) {
class_addMethod(self, sel, cfunc, "v@:");
return YES;
}
return [super resolveInstanceMethod:sel];
}
void ifunc(id self, SEL _cmd) {
NSLog(@"resolveInstanceMethod 新加的Instance方法");
}
消息转发
#pragma mark - forwardingTargetForSelector
- (id)forwardingTargetForSelector:(SEL)aSelector {
NSString *selName = NSStringFromSelector(aSelector);
if ([selName isEqualToString:@"ffunc"]) {
return [ForwardingObj new];
}
return [super forwardingTargetForSelector:aSelector];
}
#pragma mark - forwardInvocation
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSString *selName = NSStringFromSelector(aSelector);
if ([selName isEqualToString:@"fifunc"]) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return [super methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
NSString *selName = NSStringFromSelector(anInvocation.selector);
if ([selName isEqualToString:@"fifunc"]) {
[anInvocation invokeWithTarget:[ForwardingObj new]];
return;
}
[super forwardInvocation:anInvocation];
}
/////ForwardingObj.h
@interface ForwardingObj: NSObject
- (void)ffunc;
- (void)fifunc;
@end
//// ForwardingObj.m
@implementation ForwardingObj
- (void)ffunc {
NSLog(@"ForwardingObj 的ffunc方法");
}
- (void)fifunc {
NSLog(@"ForwardingObj 的fifunc方法");
}
@end
对象归档解档
- (void)decode:(NSCoder *)aDecoder {
// 一层层父类往上查找,对父类的属性执行归解档方法
Class c = self.class;
while (c &&c != [NSObject class]) {
//解档
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i = 0; i<count; i++) {
//拿到Ivar
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [NSString stringWithUTF8String:name];
//解档
id value = [aDecoder decodeObjectForKey:key];
// 利用KVC赋值
[self setValue:value forKey:key];
}
free(ivars);
c = [c superclass];
}
}
- (void)encode:(NSCoder *)aCoder {
// 一层层父类往上查找,对父类的属性执行归解档方法
Class c = self.class;
while (c &&c != [NSObject class]) {
//告诉系统归档的属性是哪些
unsigned int count = 0;//表示对象的属性个数
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i = 0; i<count; i++) {
//拿到Ivar
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);//获取到属性的C字符串名称
NSString *key = [NSString stringWithUTF8String:name];//转成对应的OC名称
//归档 -- 利用KVC
[aCoder encodeObject:[self valueForKey:key] forKey:key];
}
free(ivars);
c = [c superclass];
}
}
json转换model
...
hook系统类方法
+ (void)load {
Method old = class_getInstanceMethod(self, @selector(viewDidLoad));
Method new = class_getInstanceMethod(self, @selector(viewDidLoad_new));
method_exchangeImplementations(old, new);
}
- (void)viewDidLoad_new {
NSLog(@"before viewDidLoad method excute");
[self viewDidLoad_new];
NSLog(@"after viewDidLoad method excute");
}
- (void)viewDidLoad {
[super viewDidLoad];
}
网友评论