1 .super,isKindOfClass,isMemberOfClass 2336684744
[self class]. 打印的是Student
通过实例对象的isa指针找到找到其类对象,所以打印是Student。
[super class] 打印的也是 Student
因为super。的消息接受者还是 self。super仅仅指的是从父类寻找方法
[super superclass]
这个其实和第二个的情况是一样的,给student对象发送@selector(superclass)消息,但是superclass的实现要从父类Person类的类对象开始找起,但是superclass的实现是基类NSObject类实现的,所以从Student类的类对象和Person类的类对象开始查是没有区别的。最终输出都是student对象的父类对象,打印结果是Person。
class:获取方法调用类名
superclass:获取方法调用者的父类类名
super:编译修饰符,不是指针,指向父类标志
2.方法交换 Method-Swizzling
+ (void)load {
Method *test = class_getInstanceMethod(self, @selector(test));
Method *test2 = class_getInstanceMethod(self, @selector(test));
////> 交换两个方法的实现
method_exchangeImplementations(test, test2);
}
- (void)test2 {
[self test2];
}
3.方法交换 使用场景
1.统计页面曝光率
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[MethodSwizz swizzWithClass:[self class] originSel:NSSelectorFromString(@"dealloc") newSel:@selector(swizz_dealloc)];
});
}
- (void)swizz_dealloc{
NSLog(@" ** %@ 释放了 %s",NSStringFromClass([self class]),__func__);
// [self swizz_dealloc];
}
所有的控制器都会走这个方法
2.方法交换 来预防崩溃
把所有可能崩溃的方法 都 交换方法
- (void)avoidCrashSetValuesForKeysWithDictionary:(NSDictionary<NSString *,id> *)keyedValues {
@try {
[self avoidCrashSetValuesForKeysWithDictionary:keyedValues];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[self noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
}
}
@try里面是正常的方法
@catch 里面是崩溃的方法。崩溃后我们会走另外一个方法 可以收集崩溃信息
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
NSMethodSignature *signature = [super methodSignatureForSelector:sel];
if (!signature) {
NSLog(@"*******%@ - %@ ***un reconize selector %s!",NSStringFromClass([self class]),NSStringFromSelector(sel),__func__);
signature = [NSMethodSignature signatureWithObjCTypes:@encode(void)];
}
return signature;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
- }
利用消息转发 来处理 没有找到方法的崩溃问题
4.动态的添加方法
消息转发流程3步
消息转发的第一步:resolveInstanceMethod:(SEL)sel
+ (BOOL)resolveInstanceMethod:(SEL)sel{
if (sel == @selector(resolveMethod)) {
Method method = class_getInstanceMethod(self, @selector(test2));
///> 这个方法
class_addMethod(self, sel, method_getImplementation(method), "v16@0:8");
return YES;
}
return [super resolveInstanceMethod:sel];
}
4.动态的方法解析
@dynamic
动态运行时语言将函数决议推迟到运行时
编译时语言在编译期进行函数决议
runtime是如何通过高selector找到imp地址
就是消息传递流程
能否先编译后的类添加实力变量
不能
能否向动态添加的类添加实力变量
网友评论