iOS WebView 攔截Ajax請求

desc: 利用iOS WebView 注入js 攔截Ajax請求

iOS攔截WebView Request 請求

相信你們都不陌生,這個在WebView delegate裏有實現
貼一段代碼web

- (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裏添加自定義的信息(頭或參數)
<!--more-->ajax

可是因爲Ajax 請求不是刷新整個WebView,上面的方法中沒法捕獲。app

因而就想到了想到了經過注入js來pop 出Ajax事件來捕獲。
StackOverFlow連接ide

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來響應WebView的delegatepost

可是這樣還不能知足個人需求,由於Ajax請求已經發出去了,咱們須要在Ajax請求中加入頭

上代碼性能

+ (NSString *)jsString:(NSString *)baseString{
    return [NSString stringWithFormat:@"%@\n XMLHttpRequest.prototype.setCoustomHeader = function(){ this.setRequestHeader(\"Authorization\",\"%@\");}", baseString, [IBDataManager sharedManager].baseAuth];
}

一樣利用js注入把咱們的頭加入的Ajax請求中
達到了Ajax自定義header 與捕獲的需求ui

iOS UIWebView 有很大的性能和內存泄漏的問題
能夠考慮將UIWebView與WKWebView封裝成一套API來調用this

最近在開發新的需求和重構代碼,這段重構把WebView單獨拿出來作成了一個BaseWebViewController,爲下一步將UIWebView與WKWebView統一作準備。url

相關文章
相關標籤/搜索