title: iOS WebView 攔截Ajax請求
date: 2016-04-12 00:08:11
tags: [iOS,Ajax,WebView]
desc: 利用iOS WebView 注入js 攔截Ajax請求
iOS攔截WebView Request 請求
相信大家都不陌生,這個在WebView delegate里有實現(xiàn)
貼一段代碼
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
request = [IBWebMethod formAuthorizationRequest:request];
return [IBWebMethod interceptRequest:request BaseViewController:self];
}
ture or false 來決定WebView 是否加載請求痴脾。
可以通過new NSURLRequest賦給原request來向request里添加自定義的信息(頭或參數(shù))
但是由于Ajax 請求不是刷新整個WebView,上面的方法中無法捕獲拱礁。
于是就想到了想到了通過注入js來pop 出Ajax事件來捕獲嘹锁。
StackOverFlow鏈接
var s_ajaxListener = new Object();
s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open;
s_ajaxListener.tempSend = XMLHttpRequest.prototype.send;
s_ajaxListener.callback = function () {
console.log('mpAjaxHandler://' + this.url);
window.location='mpAjaxHandler://' + this.url;
};
s_ajaxListener.callbackDone = function (state,status) {
console.log('mpAjaxHandlerDone://' + state + ':' + status + '/' + this.url);
window.location='mpAjaxHandlerDone://' + state + ':' + status + '/' + this.url;
};
// Added this function to catch the readyState changes and request
// fake page loads.
function override_onreadystatechange(){
s_ajaxListener.callbackDone(this.readyState);
this.original_onreadystatechange();
}
XMLHttpRequest.prototype.open = function(a,b) {
if (!a) var a='';
if (!b) var b='';
s_ajaxListener.tempOpen.apply(this, arguments);
s_ajaxListener.method = a;
s_ajaxListener.url = b;
if (a.toLowerCase() == 'get') {
s_ajaxListener.data = b.split('?');
s_ajaxListener.data = s_ajaxListener.data[1];
}
}
XMLHttpRequest.prototype.send = function(a,b) {
if (!a) var a='';
if (!b) var b='';
this.setCoustomHeader();
s_ajaxListener.tempSend.apply(this, arguments);
if(s_ajaxListener.method.toLowerCase() == 'post')s_ajaxListener.data = a;
s_ajaxListener.callback();
// Added this to intercept Ajax responses for a given send().
this.original_onreadystatechange = this.onreadystatechange;
this.onreadystatechange = override_onreadystatechange;
}
可以看到重寫了XMLHttpRequest(Ajax)的open與send方法來pop出事件
在捕獲的事件中重新指定了window.location來響應(yīng)WebView的delegate
但是這樣還不能滿足我的需求豌注,因為Ajax請求已經(jīng)發(fā)出去了妙真,我們需要在Ajax請求中加入頭
上代碼
+ (NSString *)jsString:(NSString *)baseString{
return [NSString stringWithFormat:@"%@\n XMLHttpRequest.prototype.setCoustomHeader = function(){ this.setRequestHeader(\"Authorization\",\"%@\");}", baseString, [IBDataManager sharedManager].baseAuth];
}
同樣利用js注入把我們的頭加入的Ajax請求中
達到了Ajax自定義header 與捕獲的需求
iOS UIWebView 有很大的性能和內(nèi)存泄漏的問題
可以考慮將UIWebView與WKWebView封裝成一套API來調(diào)用
最近在開發(fā)新的需求和重構(gòu)代碼蝠嘉,這段重構(gòu)把WebView單獨拿出來做成了一個BaseWebViewController最疆,為下一步將UIWebView與WKWebView統(tǒng)一做準(zhǔn)備。