亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

詳解iOS開發之NSURLProtocol的那些坑

2019-10-21 18:43:46
字體:
來源:轉載
供稿:網友

NSURLProtocol

NSURLProtocol能夠讓你去重新定義蘋果的URL加載系統 (URL Loading System)的行為,URL Loading System里有許多類用于處理URL請求,比如NSURL,NSURLRequest,NSURLConnection和NSURLSession等,當URL Loading System使用NSURLRequest去獲取資源的時候,它會創建一個NSURLProtocol子類的實例,你不應該直接實例化一個NSURLProtocol,NSURLProtocol看起來像是一個協議,但其實這是一個類,而且必須使用該類的子類,并且需要被注冊。

使用場景

 不管你是通過UIWebView, NSURLConnection 或者第三方庫 (AFNetworking, MKNetworkKit等),他們都是基于NSURLConnection或者 NSURLSession實現的,因此你可以通過NSURLProtocol做自定義的操作。

  1. 重定向網絡請求
  2. 忽略網絡請求,使用本地緩存
  3. 自定義網絡請求的返回結果
  4. 一些全局的網絡請求設置

 接觸過iOS系統中URL Loading System都知道,NSURLProtocol是如此地強大,可以攔截應用內幾乎所有的網絡請求(除了WKWebView),并可以修改請求頭,返回client任意自定義的數據等等,據說很多做網絡緩存都是利用這個類的。

那么,首先講解一下NSURLProtocol怎么使用吧。

1. 定義一個NSURLProtocol的子類

在繼承NSURLProtocol中,我們需要實現

+ (BOOL)canInitWithRequest:(NSURLRequest *)request, 定義攔截請求的URL規則

- (void)startLoading, 對于攔截的請求,系統創建一個NSURLProtocol對象執行startLoading方法開始加載請求

- (void)stopLoading,對于攔截的請求,NSURLProtocol對象在停止加載時調用該方法

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request,可選方法,對于需要修改請求頭的請求在該方法中修改

下面代碼定義了一個專門攔截https請求的NSURLProtocol子類,并通過CFHttpMessageRef重新請求

@interface CFHttpMessageURLProtocol () <NSStreamDelegate> {   NSMutableURLRequest *curRequest;   NSRunLoop *curRunLoop;   NSInputStream *inputStream; }  @end  @implementation CFHttpMessageURLProtocol  /**  * 是否攔截處理指定的請求  *  * @param request 指定的請求  *  * @return 返回YES表示要攔截處理,返回NO表示不攔截處理  */ + (BOOL)canInitWithRequest:(NSURLRequest *)request {      /* 防止無限循環,因為一個請求在被攔截處理過程中,也會發起一個請求,這樣又會走到這里,如果不進行處理,就會造成無限循環 */   if ([NSURLProtocol propertyForKey:protocolKey inRequest:request]) {     return NO;   }      NSString *url = request.URL.absoluteString;      // 如果url以https開頭,則進行攔截處理,否則不處理   if ([url hasPrefix:@"https"]) {     return YES;   }   return NO; }  /**  * 如果需要對請求進行重定向,添加指定頭部等操作,可以在該方法中進行  */ + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {   return request; }  /**  * 開始加載,在該方法中,加載一個請求  */ - (void)startLoading {   NSMutableURLRequest *request = [self.request mutableCopy];   // 表示該請求已經被處理,防止無限循環   [NSURLProtocol setProperty:@(YES) forKey:protocolKey inRequest:request];   curRequest = request;   [self startRequest]; }  /**  * 取消請求  */ - (void)stopLoading {   if (inputStream.streamStatus == NSStreamStatusOpen) {     [inputStream removeFromRunLoop:curRunLoop forMode:NSRunLoopCommonModes];     [inputStream setDelegate:nil];     [inputStream close];   }   [self.client URLProtocol:self didFailWithError:[[NSError alloc] initWithDomain:@"stop loading" code:-1 userInfo:nil]]; } 

以上代碼中的startRequest方法是通過復制原始請求頭,使用CFHttpMessageRef重新發起請求的,關于這部分的代碼由于跟本文章內容關系不大,這里就先不放,有興趣的朋友可以參考我的下一篇博客。

2. 在網絡請求前注冊NSURLProtocol

 // 注冊攔截請求的NSURLProtocol [NSURLProtocol registerClass:[CFHttpMessageURLProtocol class]]; 

對于NSURLSession的請求,注冊NSURLProtocol的方式稍有不同,是通過NSURLSessionConfiguration注冊的

// NSURLSession例子 NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSArray *protocolArray = @[ [CFHttpMessageURLProtocol class] ]; configuration.protocolClasses = protocolArray; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSURLSessionTask *task = [session dataTaskWithRequest:_request]; [task resume]; 

3. 請求結束后注銷NSURLProtocol

[NSURLProtocol unregisterClass:[CFHttpMessageURLProtocol class]]; 

好了,到這里NSURLProtocol的使用方法大家應該有所了解了。下面主要講一下NSURLProtocol在使用過程中可能會遇到的坑,給自己以及需要的朋友留個提醒。

1. 上面一開始就已經說了,對于WebView的請求,目前NSURLProtocol還不能攔截WKWebView的請求,只能攔截UIWebview的,但后者好像AppStore已經不讓審核通過了(尷尬臉)。

2. NSURLProtocol在攔截NSURLSession的POST請求時不能獲取到Request中的HTTPBody,這個貌似早就國外的論壇上傳開了,但國內好像還鮮有人知,據蘋果官方的解釋是Body是NSData類型,即可能為二進制內容,而且還沒有大小限制,所以可能會很大,為了性能考慮,索性就攔截時就不拷貝了(內流滿面臉)。為了解決這個問題,我們可以通過把Body數據放到Header中,不過Header的大小好像是有限制的,我試過2M是沒有問題,不過超過10M就直接Request timeout了。。。而且當Body數據為二進制數據時這招也沒轍了,因為Header里都是文本數據,另一種方案就是用一個NSDictionary或NSCache保存沒有請求的Body數據,用URL為key,最后方法就是別用NSURLSession,老老實實用古老的NSURLConnection算了。。。

3. 使用NSURLProtocol時,在那兩個類方法可以發送同步網絡請求,而實例方法,如startLoading則進入死鎖,直至超時,原因是執行實例方法所在的線程并沒有啟動runloop,而NSURLConnection這些網絡請求需要依賴于runloop的,因此這些請求根本發不出去,所以必須使用異步請求,NSURLConnection/NSURLSession的異步請求的線程保證啟動了runloop。

以上就是我目前發現的坑,歡迎大家補充,也希望對大家開發有所幫助哈~所幸的是NSURLProtocol對于大量并發的請求支持的還不錯,不然就要棄用了~希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到IOS開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久手机免费视频| 亚洲欧美日韩另类| 精品动漫一区二区三区| 久久综合伊人77777尤物| 日韩激情av在线免费观看| 久久亚洲综合国产精品99麻豆精品福利| 亚洲女人被黑人巨大进入al| 欧美一区视频在线| 日韩精品中文字幕视频在线| 国产精品美乳一区二区免费| 亚洲情综合五月天| 国产精品视频1区| 久久精品视频播放| 日本精品一区二区三区在线播放视频| 国产精品久久久久久久久久小说| 久久免费视频网| 欧美国产欧美亚洲国产日韩mv天天看完整| 欧美巨乳在线观看| 亚洲欧洲在线免费| 黑人巨大精品欧美一区二区| 色视频www在线播放国产成人| 国产视频综合在线| 免费99精品国产自在在线| 亚洲国产精品女人久久久| 亚洲精品xxx| 久久影院在线观看| 久久久久久久999| 欧美丝袜美女中出在线| 5566日本婷婷色中文字幕97| 久久久久五月天| 综合网中文字幕| 大伊人狠狠躁夜夜躁av一区| 一区二区在线视频播放| 成年人精品视频| 亚洲第一网中文字幕| 国产精品极品在线| 91精品久久久久久久久久久久久久| 精品久久中文字幕久久av| 国产精品久久久久av免费| 5566成人精品视频免费| 亚洲第一网站免费视频| 日韩精品免费在线视频| 黄色一区二区在线观看| 日韩视频―中文字幕| 国产成人综合精品在线| 91精品国产免费久久久久久| 国产精品丝袜久久久久久不卡| 欧美国产第二页| 亚洲精品视频中文字幕| 国产精品免费视频xxxx| 欧美激情喷水视频| 亚洲va码欧洲m码| 国产精品久久久久久av福利| 38少妇精品导航| 亚洲女同精品视频| 欧美亚洲一级片| 欧美壮男野外gaytube| 国产精品视频不卡| 欧美xxxx18国产| 亚洲一区二区中文字幕| 国产乱人伦真实精品视频| 欧美电影免费观看电视剧大全| 欧洲美女7788成人免费视频| 一区二区三区视频免费在线观看| 中文字幕亚洲欧美日韩高清| 欧美精品video| 欧美国产日韩xxxxx| 精品久久久久久久久久久久| 性夜试看影院91社区| 影音先锋日韩有码| 热re91久久精品国99热蜜臀| 亚洲综合色av| 亚洲综合日韩中文字幕v在线| 日韩在线资源网| 亚洲精品视频在线播放| 91地址最新发布| 欧美激情精品久久久| 日韩欧美aaa| 亚洲影视中文字幕| 亚洲色图校园春色| 日韩视频永久免费观看| 黑人巨大精品欧美一区二区三区| 国产精品视频不卡| 欧美性理论片在线观看片免费| 国内揄拍国内精品| 国产精品你懂得| 欧美激情国产日韩精品一区18| 亚洲精品视频免费在线观看| 国产日韩换脸av一区在线观看| 黄色成人在线免费| 成人字幕网zmw| 欧美极品少妇xxxxx| 国产综合福利在线| 亚洲一区二区三区在线免费观看| 欧美日韩午夜视频在线观看| 国内精品模特av私拍在线观看| 久久亚洲精品视频| 最新91在线视频| 一本一本久久a久久精品牛牛影视| 亚洲色图av在线| 欧美一区二区三区图| 777777777亚洲妇女| 国产69久久精品成人| 国产精品日韩在线播放| 国产成人福利视频| 亚洲一区二区久久久久久久| 欧美精品中文字幕一区| 91在线视频免费| 91美女片黄在线观| 久久视频免费在线播放| 中文字幕国产日韩| 欧美性生交大片免费| 91精品久久久久久久久中文字幕| 91日本在线观看| 69久久夜色精品国产69| 亚洲大尺度美女在线| 国产在线观看不卡| 国产精品久久久久久五月尺| 成人亚洲欧美一区二区三区| 日韩av中文字幕在线播放| 国产精品高潮呻吟久久av无限| 欧美激情伊人电影| 欧美性色19p| 亚洲精品自拍偷拍| 亚洲人成人99网站| 亚洲欧美一区二区精品久久久| 日韩欧美999| 中文字幕亚洲在线| 欧美性猛交xxxx富婆弯腰| 亚洲精品福利在线| 日韩精品免费在线播放| 亚洲欧美一区二区三区四区| 精品国产一区二区在线| 欧美成人激情视频| 欧美激情在线视频二区| 国产福利精品视频| 国产欧美精品一区二区| 亚洲va国产va天堂va久久| 国产精品日本精品| 欧美在线激情视频| 91色在线观看| 午夜精品免费视频| 91国产高清在线| 欧美孕妇性xx| 永久免费看mv网站入口亚洲| 久久久久中文字幕| 国产成人精品在线播放| 亚洲午夜未满十八勿入免费观看全集| 国产欧美一区二区三区四区| 亚洲激情在线观看视频免费| 欧美高清videos高潮hd| 国产精品视频区1| 亚洲欧美三级在线| 亚洲va电影大全| www.色综合| 日韩成人av一区| 色噜噜亚洲精品中文字幕| 欧美性猛交xxxx富婆弯腰| 国产精品成人免费电影| 91po在线观看91精品国产性色| 精品无人区乱码1区2区3区在线| 日韩三级成人av网| 欧美日韩亚洲一区二| 97视频在线观看视频免费视频|