码无界IOS And AndroidiOS iOS Developer

iOS高级开发 RunTime机制讲解三

2016-03-24  本文已影响294人  kevinLY

下载DEMO:https://github.com/sleepsheep/RunTimeDemo03

1、系统类方法实现部分替换
void method_exchangeImplementations(Method m1, Method m2)
参数说明:1、Method m1 待交换的方法1 2、Method m2 待交换的方法2
2、自定义类的方法实现部分替换
参考方法(method_exchangeImplementations)的注释说明
3、覆盖系统的方法
4、自动序列化 见 NSObject+AutoEncodeDecode.h

代码:

@implementation TestClass

//3、覆盖系统的方法
IMP cFuncPointer0;
IMP cFuncPointer1;
IMP cFuncPointer2;

NSString* CustomUppercaseString(id self,SEL _cmd) {
    printf("原始的方法的名字是CustomUppercaseString");
    
    NSString *string = cFuncPointer0(self, _cmd);
    
    return string;
}

NSArray* CustomComponentsSeparatedByString(id self, SEL _cmd, NSString *str) {
    printf("原始的方法的名字是CustomComponentsSeparatedByString");
    
    return cFuncPointer1(self, _cmd, str);
}

bool customIsEqualToString(id self, SEL _cmd, NSString *str) {
    printf("原始的方法的名字是customIsEqualToString");
    return cFuncPointer2(self, _cmd, str);
}

- (void)replaceMethod {
    cFuncPointer0 = [NSString instanceMethodForSelector:@selector(uppercaseString)];
    class_replaceMethod([NSString class], @selector(uppercaseString), (IMP)CustomUppercaseString, "@@:");
    
    cFuncPointer1 = [NSString instanceMethodForSelector:@selector(componentsSeparatedByString:)];
    class_replaceMethod([NSString class], @selector(componentsSeparatedByString:), (IMP)CustomComponentsSeparatedByString, "@@:@");
    
    cFuncPointer2 = [NSString instanceMethodForSelector:@selector(isEqualToString:)];
    class_replaceMethod([NSString class], @selector(isEqualToString:), (IMP)customIsEqualToString, "B@:@");//B@:@ ---- 返回值 self _sel 参数
}


//2、自定义类的方法实现部分替换
- (void)testLog1 {
    NSLog(@"testLog1");
}

- (void)testLog2 {
    NSLog(@"testLog2");
}

- (void)methodSetimplement {
    Method m1 = class_getInstanceMethod([TestClass class], @selector(testLog1));
    Method m2 = class_getInstanceMethod([TestClass class], @selector(testLog2));
    IMP imp1 = method_getImplementation(m1);
    IMP imp2 = method_getImplementation(m2);
    method_setImplementation(m1, imp2);
    method_setImplementation(m2, imp1);
    
    //IMP imp1 = method_getImplementation(m1);
    //IMP imp2 = method_getImplementation(m2);
    //method_setImplementation(m1, imp2);
    //method_setImplementation(m2, imp1);
}

- (void)testMyMethodExchange {
    [self methodSetimplement];
    
    [self testLog1];//testLog2
    
    [self testLog2];//testLog1
}

//1、系统类方法实现部分替换
- (void)methodExchange {
    Method method1 = class_getInstanceMethod([NSString class], @selector(lowercaseString));
    Method method2 = class_getInstanceMethod([NSString class], @selector(uppercaseString));
    method_exchangeImplementations(method1, method2);//交换两个方法后,两个方法的功能相反
    NSLog(@"lowerCase:%@", [@"ssssAAAAssss" lowercaseString]);//lowerCase:SSSSAAAASSSS
    NSLog(@"upperCase:%@", [@"ssssAAAAssss" uppercaseString]);//upperCase:ssssaaaassss
}


注:工程中需要设置 Build Settings里的参数:enable strict checking of objc_msgsend calls 为 no why

FE73F5AD-7E79-489A-BC0A-D3FB7B14D1A8.png
上一篇 下一篇

猜你喜欢

热点阅读