Method-Swizzling实战-实现iOS原生网络请求性能采集

一、方法交换实现步骤(实例方法和类方法处理逻辑类似)

1.检查原类(要被替换方法的类)的原实例方法是否存在,如果不存在,则不交换;
2.检查新类(最终被使用的方法所在的类)的新实例方法是否存在,如果不存在,则不交换;
3.检索原实例方法所在的真实父类,防止循环调用;
4.如果原类和新类不是一个类,则需要将新类的新实例方法添加到原类;
(1)如果添加失败,说明该方法已经存在,则不需要再做交换;
(2)如果添加成功,需要从原类重新获取新添加的实例方法,否则可能交换失败。
5.将原类的新实例方法交换原类的原实例方法。
6方法交换的时机可以自己控制,确保能够及时交换就可以。
7.关键方法:
class_getInstanceMethod(Class _Nullable cls, SEL _Nonnull name)
class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, 
                const char * _Nullable types) 
method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2) 

二、iOS原生网络请求交换范围

1.NSURLConnection
2.NSURLSession

三、iOS原生网络请求交换步骤,以NSURLConnection为例,NSURLSession类似。

1.新增一个类,声明为NSURLConnection的一个新类别。

2.首先需要交换非代理方式的的请求API。

(1)NSURLConnection类有两个:

+(NSData*)sendSynchronousRequest:(NSURLRequest*)request returningResponse:(NSURLResponse* _Nullable* _Nullable)response error:(NSError**)error;
+(void)sendAsynchronousRequest:(NSURLRequest*)request queue:(NSOperationQueue*)queue completionHandler:(void (^)(NSURLResponse* _Nullable response, NSData* _Nullable data, NSError* _Nullable connectionError)) handler;

(2)新方法如下:

+(NSData*)swizzle_sendSynchronousRequest:(NSURLRequest*)request returningResponse:(NSURLResponse* _Nullable* _Nullable)response error:(NSError **)error
{
    //调用原本的方法
    NSData *resultData = [self swizzle_sendSynchronousRequest:request returningResponse:response error:error];
    return resultData;
}
+(void)swizzle_sendAsynchronousRequest:(NSURLRequest*)request queue:(NSOperationQueue*)queue completionHandler:(void (^)(NSURLResponse* _Nullable swizzle_response, NSData* _Nullable swizzle_data, NSError* _Nullable swizzle_connectionError)) swizzle_handler
{
    //如果回调方法为空,则直接返回,不做截获处理
    if (swizzle_handler == nil)
    {
        return [self swizzle_sendAsynchronousRequest:request queue:queue completionHandler:nil];
    }
    
    //调用原本的方法
    [self swizzle_sendAsynchronousRequest:request queue:queue
                           completionHandler:^(NSURLResponse* _Nullable response, NSData* _Nullable data, NSError* _Nullable connectionError)
     {
         //回调上层
         swizzle_handler(response, data, connectionError);
     }];
}

3.代理方式发送请求的API交换

(1)交换初始化方法,并在初始化方法中获取代理对象,并交换代理对象的网络代理方法。

原方法:
-(NSURLConnection*)initWithRequest:(NSURLRequest*)request delegate:(nullable id)delegate startImmediately:(BOOL)startImmediately;
- (NSURLConnection*)initWithRequest:(NSURLRequest*)request delegate:(nullable id)delegate;

新方法:
-(NSURLConnection*)swizzle_initWithRequest:(NSURLRequest*)request delegate:(nullable id)delegate startImmediately:(BOOL)startImmediately
{
    //设置代理方法交换,交换必要的方法即可
    [self methodsSwizzleForDelegate:delegate];

    //调用原本的方法
    return  [self swizzle_initWithRequest:request delegate:delegate startImmediately:startImmediately];
}
- (NSURLConnection*)swizzle_initWithRequest:(NSURLRequest*)request delegate:(nullable id)delegate
{
    //设置代理方法交换,交换必要的方法即可
    [self methodsSwizzleForDelegate:delegate];
    
    //调用原本的方法
    return  [self swizzle_initWithRequest:request delegate:delegate];;
}

(2)代理方法交换,只列举其中几个,可以扩展
- (void)swizzle_connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    //调用原本的方法
    [self swizzle_connection:connection didReceiveResponse:response];
}
-(void)swizzle_connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    //调用原本的方法
    [self swizzle_connection:connection didReceiveData:data];
}
-(void)swizzle_connectionDidFinishLoading:(NSURLConnection *)connection
{
    //调用原本的方法
    [self id_swizzle_connectionDidFinishLoading:connection];
}
-(void)swizzle_connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    //调用原本的方法
    [self id_swizzle_connection:connection didFailWithError:error];
}

四、请求性能数据采集

请求的整个过程和关键时机都经过我们自己的代码,性能指标数据采集不是很简单?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499857.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java8新特性(1)--- lambda表达式

java8新特性(1)— lambda表达式 函数式编程,简化开发 新增语法(->) package com.common.jdk8;// 试想,如果在jdk1.7中,我们要实现基于这个接口的加法运算,一般会这样 // 先创建…

iOS中WebKit框架应用与解析

一、引言 在iOS8之前,在应用中嵌入网页通常需要使用UIWebView这样一个类,这个类通过URL或者HTML文件来加载网页视图,功能十分有限,只能作为辅助嵌入原生应用程序中。虽然UIWebView也可以做原生与JavaScript交互的相关处理&#xf…

java8新特性(2)--- 方法引用

java8新特性(2)— 方法引用 新增语法双冒号(::) package com.common.jdk8;import java.util.Arrays; import java.util.List;//方法引用 public class Jdk8Test2 {public static void main(String[] args) {//构造器引用&#x…

让WKWebView支持NSURLProtocol

NSURLProtocol能够拦截UIWebView内所有的请求,但是WKWebView 中的请求却完全不遵从这一规则,只是象征性调用canInitWithRequest方法,之后的整个请求流程似乎就与 NSURLProtocol 完全无关了。使我一度认为WKWebView请求不遵守NSURLProtocol协议…

java8新特性(3)--- 函数式接口

java8新特性(3)— 函数式接口 有且仅有一个抽象方法 package com.common.jdk8;import java.util.Arrays; import java.util.List; import java.util.function.Predicate;// 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,…

Git仓库迁移,包括所有的分支、标签、日志

仅三行命令即可完成: git clone --bare http://域名/分组/仓库名称.git cd 仓库名称.git git push --mirror http://新域名/新分组/新仓库名称.git

java8新特性(4)— Stream流

java8新特性(4)— Stream流 遍历集合更强大 package com.common.jdk8;import java.util.*; import java.util.stream.Collectors;//Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。 //Stream 使用一种类似用…

二、工作量证明链-区块链技术的雏形

用算法解决难题——区块链技术的雏形 构造出一个完美的、可以解决问题的“拜占庭容错系统”是一个不小的挑战。而且构造出来以后,其是否真的有效,能否经得起时间的考验与各方的质疑,这些都关乎着这个系统未来的命运与其创造群体的声誉。 2008…

CocoaPods通过网络代理执行资源更新

一、使用网络代理 首先在电脑设置网络代理配置。 二、设置git的http、https代理 1.查看git是否已经设置网络代理 首先可以先查本地的git配置有没有配置http/https代理:git config --global -e 如果没有看到 [http]proxy和 [https]proxy就代表没有设置http/http…

java8新特性(5)— Optional 类

java8新特性(5)— Optional 类 空指针解决方案 package com.common.jdk8;import java.util.Optional;//Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。 //Optional 是个容器&…

五、工作量证明链解决拜占庭将军问题之模拟程序(Objective-C)

一、概述: 此程序用来模拟工作量证明链如何解决拜占庭将军问题,使用Objective-C语言,需要使用Xcode开发工具运行并执行演示,演示结果打印在Xcode控制台。 二、示例程序: 程序下载地址:工作量证明链解决拜…

java8新特性(6)— 日期与时间

java8新特性(6)— 日期与时间 全新的日期与时间处理 package com.common.jdk8;import java.time.*;//Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。 //在旧版的 Java 中,日期时间 API 存在诸多问题&#xff…

六、区块链主流共识算法浅析

转自:http://www.cocoachina.com/cms/wap.php?actionarticle&id22240。 一、概述: 1.工作量证明(Proof of Work): 通过所有节点的工作量竞争来达成一致。竞争的是运算力。 2.权益证明(Proof of S…

java8新特性(7)— Base64

java8新特性(7)— Base64 新增Base64工具类 package com.common.jdk8;import java.io.UnsupportedEncodingException; import java.util.Base64; import java.util.UUID;//在Java 8中,Base64编码已经成为Java类库的标准。 //Java 8 内置了 …

修改git历史提交的commit信息

本文是基于idea的操作,亲测可用 前言: 很多公司都会自定义 Git - 使用强制策略,那么他的commit信息就会有固定的格式,一旦不是这个格式,就会出现push失败 但是push失败,很多也只在dev和master分支做强制限…

七、区块链如何运用merkle tree验证交易真实性

转载自:https://www.tangshuang.net/4117.html 本文假设你已经知道区块链中merkle tree的原理,现在搞明白具体怎么来实现交易真实性验证。 Merkle Tree 这个小节简述一下merkle的原理。简单说,merkle tree就是一个hash二叉树,父…

idea端口占用解决记录

idea端口占用解决 每次占用,每次都要百度,路子很清晰了,记录下 报错:The port may already be in use or the connector may be misconfigured. 解决: 1.cmd 2.netstat -ano|findstr 你的端口号 举例:…

西安软件行业闲谈

尘埃落定,最终选择了西安 讲真,今年年初,就萌生了回西安的想法,毕竟北漂几年,该回了 当初还想着去上海两年,再去深圳两年,好好体验下各个一线城市的不同魅力 性格就是这样,不甘平凡…

消息队列(1):一个消息队列应该有的特点

消息队列常见场景 异步解耦 削峰填谷 日志收集分析 代替事务,最终一致 消息队列特点 消息队列之所以能异步,就是因为消息并不是实时处理的,那肯定会有一个存储消息,处理消息的地方,才能达到异步效果。 所以最简单的…

消息队列(2):常见的消息队列协议

协议很常见,只要是通信,就会用到协议,就像我们说话的语言一样,不同的语言连通着不同的人群。 所以说,消息队列也是一样,想要互相通信,就要使用同一种协议。 每个协议下的消息队列,都…