利用NSURLProtocol攔截WKWebView的請求
我們知道 ,ios 8.0以后资锰,apple給出了一個WKWebView來替換 UIWebView,前者比后者在加載速度方面優(yōu)化了很多,但是也有不少坑點浪慌,比如在攔截wkwebView的請求上深员,apple始終沒有給出明確的API供開發(fā)者使用牵舱,正常情況下瓷翻,我們自定義一個NSURLProtocol類仰税,然后在AppDelegate里面register一波祸憋,就可以攔截到app內(nèi)部所有的網(wǎng)絡(luò)請求,但是你會發(fā)現(xiàn)肖卧,wkwebView并不吃這一套蚯窥,what the fuck!,這一點在網(wǎng)上有人說wkwebView的請求是在單獨的進程里面,為了性能方面的考慮拦赠,所以不走NSURLProtocol巍沙,但是通過打斷點會發(fā)現(xiàn),它會走一下+ (BOOL)canInitWithRequest:(NSURLRequest *)request
,然而這就尷尬了荷鼠,為啥他會走一下句携,然后就一直不走了呢?于是我開始去研究了一波技術(shù)討論允乐,請教了一些大牛矮嫉,找到了解決方案:寫一個單獨的NSURLProtocol類的分類方法,這里要提醒一下:由于這是私有方法牍疏,可能導(dǎo)致上線被拒!!!
.h文件:
+ (void)wk_registerScheme:(NSString*)scheme;
+ (void)wk_unregisterScheme:(NSString*)scheme;
.m文件:
FOUNDATION_STATIC_INLINE Class ContextControllerClass() {
static Class cls;
if (!cls) {
cls = [[[WKWebView new] valueForKey:@"browsingContextController"] class];
}
return cls;
}
FOUNDATION_STATIC_INLINE SEL RegisterSchemeSelector() {
return NSSelectorFromString(@"registerSchemeForCustomProtocol:");
}
FOUNDATION_STATIC_INLINE SEL UnregisterSchemeSelector() {
return NSSelectorFromString(@"unregisterSchemeForCustomProtocol:");
}
@implementation NSURLProtocol (WebKitSupport)
+ (void)wk_registerScheme:(NSString *)scheme {
Class cls = ContextControllerClass();
SEL sel = RegisterSchemeSelector();
if ([(id)cls respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[(id)cls performSelector:sel withObject:scheme];
#pragma clang diagnostic pop
}
}
+ (void)wk_unregisterScheme:(NSString *)scheme {
Class cls = ContextControllerClass();
SEL sel = UnregisterSchemeSelector();
if ([(id)cls respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[(id)cls performSelector:sel withObject:scheme];
#pragma clang diagnostic pop
}
}
然后在AppDelegate里面去注冊一波scheme蠢笋,一般是注冊http和https,然后打一波斷點你就會發(fā)現(xiàn),可以攔截了鳞陨,可以為所欲為了昨寞,一般對wkwebView的攔截的原因一般是要加一些特定的請求頭或者攔截廣告(接觸的項目里面是這樣干的)
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
在這里進行過濾判斷,
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
這里面可以拿到被攔截的請求厦滤,可以在這里面對這個request進行二次處理援岩,然后在startLoading方法里面自己進行自定義的處理!