#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

results matching ""

    No results matching ""