一、方法交换实现步骤(实例方法和类方法处理逻辑类似)
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.NSURLConnection2.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];
}