iOS开发_HOOK

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_21051503/article/details/81090201

我们在使用NSURLRequest时,传入请求地址URL,但是如果URL中有中文的话,我们会发现NSURLRequest的请求地址会报空

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL * url =[NSURL URLWithString:@"http://www.baidu.com/中文"];
    NSURLRequest * request =[NSURLRequest requestWithURL:url];
    NSLog(@"%@",request);
}
//2018-04-23 10:08:23.719236+0800 003-HOOK[947:5550247] <NSURLRequest: 0x60400000e6d0> { URL: (null) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

那我们有没有办法改进呢?做下尝试

我们创建一个继承自NSURL的类,命名为HOOK,然后新建一个方法

#import <Foundation/Foundation.h>

@interface NSURL (HOOK)

+(instancetype)HK_URLWithString:(NSString *)URLString;

@end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
#import "NSURL+HOOK.h"

@implementation NSURL (HOOK)

+(instancetype)HK_URLWithString:(NSString *)URLString{
    NSURL * url = [NSURL URLWithString:URLString];
    if(url ==nil){
        NSLog(@"空了");
    }
    return url;
}
@end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

此时我们需要在ViewController.h导入NSURL+HOOK.h文件,还需要修改调用的方法名HK_URLWithString

#import "ViewController.h"
#import "NSURL+HOOK.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL * url =[NSURL HK_URLWithString:@"http://www.baidu.com/中文"];
    NSURLRequest * request =[NSURLRequest requestWithURL:url];
    NSLog(@"%@",request);
}

//2018-04-23 10:30:38.145984+0800 003-HOOK[1168:5566807] 空了
//2018-04-23 10:30:38.146393+0800 003-HOOK[1168:5566807] <NSURLRequest: 0x604000200480> { URL: (null) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

那有没有更简洁的方式呢?可以利用Runtime运行时改变方法调用的顺序,在NSURL+HOOK.m文件修改

//
//  NSURL+HOOK.m
//  003-HOOK
//
//  Created by mac on 2018/4/23.
//  Copyright © 2018年 mac. All rights reserved.
//  哪里HOOK?
/**
 利用Runtime运行时改变方法调用的顺序
 */

#import "NSURL+HOOK.h"
#import <objc/runtime.h>

@implementation NSURL (HOOK)

+(void)load{
    //获取两个Method
    Method URLWithStr = class_getClassMethod(self, @selector(URLWithString:));
    Method HKWithStr = class_getClassMethod(self, @selector(HK_URLWithString:));
    //交换方法的IMP
    method_exchangeImplementations(URLWithStr, HKWithStr);
}
//重写URLWithString
//+(instancetype)URLWithString:(NSString *)URLString{
//    NSURL * 
//}
+(instancetype)HK_URLWithString:(NSString *)URLString{
    NSURL * url = [NSURL URLWithString:URLString];
    if(url ==nil){
        NSLog(@"空了");
    }
    return url;
}
@end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

此时,我们在ViewController.h文件还是使用最初的代码,一个代码都不需要修改

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL * url =[NSURL URLWithString:@"http://www.baidu.com/中文"];
    NSURLRequest * request =[NSURLRequest requestWithURL:url];
    NSLog(@"%@",request);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

我们就可以达到我们的目的,这种方式叫做方法欺骗。利用的就是runtime的HOOK。

但是我们发现程序并没有我们想象的顺利运行,而是卡死了 
这里写图片描述

这是因为我们修改了消息发送时候真正的方法实现。

这里写图片描述

我们在ViewController中调用URLWithString方法,实际运行的是HK_URLWithString,而在NSURL+HOOK.m文件中我们调用了URLWithString方法,实际运行的仍然是它本身,所以就不会不断循环,导致程序内存暴增,而卡死崩溃。那我们怎么解决呢?很简单,我们把NSURL+HOOK.m文件中的URLWithString替换成HK_URLWithString

这里写图片描述

#import "NSURL+HOOK.h"
#import <objc/runtime.h>
@implementation NSURL (HOOK)
+(void)load{
    //获取两个Method
    Method URLWithStr = class_getClassMethod(self, @selector(URLWithString:));
    Method HKWithStr = class_getClassMethod(self, @selector(HK_URLWithString:));
    //交换方法的IMP
    method_exchangeImplementations(URLWithStr, HKWithStr);
}
//重写URLWithString?
//+(instancetype)URLWithString:(NSString *)URLString{
//    NSURL * 
//}
+(instancetype)HK_URLWithString:(NSString *)URLString{
    NSURL * url = [NSURL HK_URLWithString:URLString];
    if(url ==nil){
        NSLog(@"空了");
    }
    return url;
}
@end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在运行,我们发现就可以达到我们所设想的目的。我们可以不需要修改原来项目中的代码,仅仅把NSURL+HOOK.h和NSURL+HOOK.m拖进项目中就可以实现了

2018-04-23 11:22:36.367259+0800 003-HOOK[1748:5624887] 空了
2018-04-23 11:22:36.367636+0800 003-HOOK[1748:5624887] <NSURLRequest: 0x604000019110> { URL: (null) }
  • 1
  • 2

gitHub示例:https://github.com/Goddreamwt/iOS_HOOK.git

猜你喜欢

转载自blog.csdn.net/qq_21051503/article/details/81090201