3-4 super self 和 Method-Swizzling 消息交换

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 *)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地址
就是消息传递流程

能否先编译后的类添加实力变量
不能

能否向动态添加的类添加实力变量

你可能感兴趣的:(3-4 super self 和 Method-Swizzling 消息交换)