#import <Foundation/Foundation.h>
@interface NSObject (LGRuntime)
/**
swizzle 类方法
@param methodList 需要替换的方法名数组
@param prefix 替换的方法前缀(替换的方法为“原方法+前缀”)
*/
+ (void)lg_swizzleInstanceMethodList:(NSArray<NSString *> *)methodList prefix:(NSString *)prefix;
/**
swizzle 类方法
@param oriSel 原有的方法
@param swiSel swizzle的方法
*/
+ (void)lg_swizzleClassMethodWithOriginSel:(SEL)oriSel swizzledSel:(SEL)swiSel;
/**
swizzle 实例方法
@param oriSel 原有的方法
@param swiSel swizzle的方法
*/
+ (void)lg_swizzleInstanceMethodWithOriginSel:(SEL)oriSel swizzledSel:(SEL)swiSel;
#pragma mark -
/**
判断方法是否在子类里override了
@param cls 传入要判断的Class
@param sel 传入要判断的Selector
@return 返回判断是否被重载的结果
*/
- (BOOL)lg_isMethodOverride:(Class)cls selector:(SEL)sel;
/**
动态创建绑定selector的类
tip:每当无法找到selectorcrash转发过来的所有selector都会追加到当前Class上
@param aSelector 传入selector
@return 返回创建的类
*/
+ (Class)lg_addMethodToStubClass:(SEL)aSelector;
@end
实现:
//
// NSObject+LGRuntime.m
// Legend
//
// Created by againXu on 2017/10/25.
// Copyright © 2017年 congacademy. All rights reserved.
//
#import "NSObject+LGRuntime.h"
#import <objc/runtime.h>
char * const kProtectCrashProtectorName = "kProtectCrashProtector";
void ProtectCrashProtected(id self, SEL sel) {
}
@implementation NSObject (LGRuntime)
+ (void)lg_swizzleInstanceMethodList:(NSArray<NSString *> *)methodList prefix:(NSString *)prefix {
[methodList enumerateObjectsUsingBlock:^(NSString *selString, NSUInteger idx, BOOL *stop) {
NSString *mySelString = [prefix stringByAppendingString:selString];
Method originalMethod = class_getInstanceMethod(self, NSSelectorFromString(selString));
Method myMethod = class_getInstanceMethod(self, NSSelectorFromString(mySelString));
method_exchangeImplementations(originalMethod, myMethod);
}];
}
+ (void)lg_swizzleClassMethodWithOriginSel:(SEL)oriSel swizzledSel:(SEL)swiSel {
Class cls = object_getClass(self);
Method originAddObserverMethod = class_getClassMethod(cls, oriSel);
Method swizzledAddObserverMethod = class_getClassMethod(cls, swiSel);
[self lg_swizzleMethodWithOriginSel:oriSel oriMethod:originAddObserverMethod swizzledSel:swiSel swizzledMethod:swizzledAddObserverMethod class:cls];
}
+ (void)lg_swizzleInstanceMethodWithOriginSel:(SEL)oriSel swizzledSel:(SEL)swiSel {
Method originAddObserverMethod = class_getInstanceMethod(self, oriSel);
Method swizzledAddObserverMethod = class_getInstanceMethod(self, swiSel);
[self lg_swizzleMethodWithOriginSel:oriSel oriMethod:originAddObserverMethod swizzledSel:swiSel swizzledMethod:swizzledAddObserverMethod class:self];
}
+ (void)lg_swizzleMethodWithOriginSel:(SEL)oriSel
oriMethod:(Method)oriMethod
swizzledSel:(SEL)swizzledSel
swizzledMethod:(Method)swizzledMethod
class:(Class)cls {
BOOL didAddMethod = class_addMethod(cls, oriSel, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(cls, swizzledSel, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
} else {
method_exchangeImplementations(oriMethod, swizzledMethod);
}
}
#pragma mark -
+ (Class)lg_addMethodToStubClass:(SEL)aSelector {
Class ProtectCrashProtector = objc_getClass(kProtectCrashProtectorName);
if (!ProtectCrashProtector) {
ProtectCrashProtector = objc_allocateClassPair([NSObject class], kProtectCrashProtectorName, sizeof([NSObject class]));
objc_registerClassPair(ProtectCrashProtector);
}
class_addMethod(ProtectCrashProtector, aSelector, (IMP)ProtectCrashProtected, "v@:");
return ProtectCrashProtector;
}
- (BOOL)lg_isMethodOverride:(Class)cls selector:(SEL)sel {
IMP clsIMP = class_getMethodImplementation(cls, sel);
IMP superClsIMP = class_getMethodImplementation([cls superclass], sel);
return clsIMP != superClsIMP;
}
@end