91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

詳解如何攔截iOS所有網絡請求

發布時間:2020-09-14 17:46:14 來源:腳本之家 閱讀:294 作者:LvesLi 欄目:移動開發

背景

最近在研究iOS無埋點統計技術,我們的統計SDK主要分兩部分:點擊事件和網絡請求。統計所有的點擊事件是采用Method Swizzling實現的,可以做到使用中不需要一行代碼實現統計所有事件,具體細節將來我會專門抽幾篇文章介紹。

今天主要說說如何統計APP中的所有網絡請求。公司網絡請求如果不是靜態庫或者框架,很容易想到在網絡請求發送和返回時添加統計的代碼。如何在不修改原來代碼(或者修改最少)的基礎上攔截所有的請求呢,能不能從系統層面上攔截回調呢?答案是肯定的,蘋果有一個黑魔法NSURLProtocol

介紹

NSURLProtocol是iOS URL Loading System中的一部分,看起來像是一個協議,但其實這是一個類,而且必須使用該類的子類,并且需要被注冊。先看看他在URL Loading System中的位置:

詳解如何攔截iOS所有網絡請求

使用場景

不管是UIWebView還是URLSession還是第三方的AFNetWorkongAlamofire或者SDWebImage他們都是基于URLSession或者NSURLConnection來實現的,因此可以通過NSURLProtocol做自定義操作。

  1. 重定向網絡請求
  2. 攔截網絡加載,采用本地緩存
  3. 修改Request信息
  4. 自定義返回結果
  5. 對請求進行HTTPDNS解析,動態設置Host,解決不同網絡下客戶端不能訪問的情況

實現

首先要繼承NSURLProtocol創建自定義的類,然后重寫startLoading、stopLoading添加我們的統計代碼就可以了:

static NSString * const hasInitKey = @"LLMarkerProtocolKey";
@interface LLMarkerURLProtocol : NSURLProtocol
@end

子類實現的NSURLProtocol方法:

1.0 +(BOOL)canInitWithRequest:(NSURLRequest *)request;子類是否能響應該請求。

+(BOOL)canInitWithRequest:(NSURLRequest *)request{
 if ([NSURLProtocol propertyForKey:hasInitKey inRequest:request]) {
  return NO;
 }
 return YES;
}

2.0  +(NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request;自定義網絡請求,如果不需要處理直接返回request。

+(NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request{
 return request;
}

3.0  -(void)startLoading 開始網絡請求,需要在該方法中發起一個請求,對于NSURLConnection來說,就是創建一個NSURLConnection,對于NSURLSession,就是發起一個NSURLSessionTask 。一般下載前需要設置該請求正在進行下載,防止多次下載的情況發生。

-(void)startLoading{
 NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
 //做下標記,防止遞歸調用
 [NSURLProtocol setProperty:@YES forKey:hasInitKey inRequest:mutableReqeust];
 self.connection = [NSURLConnection connectionWithRequest:mutableReqeust delegate:self];
}

4.0  -(void)stopLoading 停止相應請求,清空請求Connection 或Task。

-(void)stopLoading{
 [self.connection cancel];
}

5.0 實現NSURLConnectionDelegateNSURLConnectionDataDelegate或者NSURLSessionTaskDelegate

#pragma mark - NSURLConnectionDelegate

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
 [self.client URLProtocol:self didFailWithError:error];
}
#pragma mark - NSURLConnectionDataDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
 self.responseData = [[NSMutableData alloc] init];
 [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
 [self.responseData appendData:data];
 [self.client URLProtocol:self didLoadData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
 [self.client URLProtocolDidFinishLoading:self];
}

使用

一、在AppDelegate中注冊:

[NSURLProtocol registerClass:[LLMarkerURLProtocol class]];

這樣能攔截UIWebView和自定義的請求了,如果要攔截AFNetWorking、Alamofire等第三方請求還需要做一些修改。

二、LLMarkerURLProtocol中添加自定義NSURLSessionConfiguration方法:

+ (NSURLSessionConfiguration *) defaultSessionConfiguration{
 NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
 NSMutableArray *array = [[config protocolClasses] mutableCopy];
 [array insertObject:[self class] atIndex:0];
 config.protocolClasses = array;
 return config;
}

攔截第三方網絡庫方法就是讓第三方使用我們這個NSURLSessionConfiguration。因為我們在自己的NSURLSessionConfiguration 中的protocolClasses中注冊了自己類。

三、 下面以Alamofire為例

1.0 繼承Alamofire.SessionManager 自定義SessionManager

class LLSessionManger: Alamofire.SessionManager{
 public static let sharedManager: SessionManager = {
  let configuration = LLMarkerURLProtocol.defaultSessionConfiguration()
  configuration?.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
  let manager = Alamofire.SessionManager(configuration: configuration!)
  return manager
 }()
}

2.0 使用 LLSessionManger進行網絡請求

let manager = LLSessionManger.sharedManager
manager.request("https://httpbin.org/get").responseJSON { (response) in
 if let JSON = response.result.value {
  print("JSON: \(JSON)")
 }
}

注意:AFNetWorking、SDWebimage等第三方庫的修改和Alamofire類似,找到使用NSURLSessionConfiguration的地方,換成LLMarkerURLProtocol的defaultSessionConfiguration就可以了。

看到這你可能發現,如果使用Alamofire進行網絡請求,我們還是修改了原來的代碼,下篇文章單獨介紹如何不修改原來代碼,通過注冊Alamofire通知方式,攔截Alamofire的網絡請求。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

铁力市| 福建省| 栖霞市| 宁南县| 麦盖提县| 页游| 江达县| 米林县| 卫辉市| 磴口县| 墨江| 宜宾县| 丹棱县| 新昌县| 偃师市| 浦县| 集贤县| 什邡市| 无锡市| 西乡县| 古田县| 清新县| 中西区| 军事| 新巴尔虎左旗| 长沙市| 桓台县| 海口市| 黄山市| 淮安市| 屯留县| 平谷区| 和政县| 琼海市| 镇赉县| 珠海市| 赣榆县| 新源县| 通城县| 花莲市| 丹江口市|