请稍侯

iOS问题汇总之iOS应用 - 浏览器及WKWebView关键点

08 September 2020

iOS问题汇总之iOS应用 - 浏览器及WKWebView关键点

WKWebView

关键代码

self.wkWebView.allowsBackForwardNavigationGestures = YES;
[self.wkWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
[self.wkWebView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:nil];

关键类与方法

WKUserContentController

//添加消息处理

self.configuration.userContentController = [WKUserContentController new];
[self.configuration.userContentController addScriptMessageHandler:self name:@"webViewReload"];

//添加UserScript

\- (void)addUserScript:(WKUserScript *)userScript;

//处理js端消息

\- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;

//处理当接收到验证窗口时

\- (void)  webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;

//切换用户代理模式
//私有方法:- (void)_setCustomUserAgent:(id)arg1;

WKNavigationDelegate
decidePolicyForNavigationAction:

WKScriptMessageHandler

WKUIDelegate
//处理页面的promt弹窗

//此方法可以让我们得知点击了哪个buttin,回传button index值
UIActionSheetDelegate
\- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex

WKWebViewConfiguration WKProcessPool 单例

configuration.processPool = [WKProcessPool new]; 

//判断跳转类型,在做容器内外跳转可借用

\- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation 

if(navigationAction.navigationType == WKNavigationTypeReload ||
            navigationAction.navigationType == WKNavigationTypeBackForward ||
            navigationAction.navigationType == WKNavigationTypeFormSubmitted ||
            navigationAction.navigationType == WKNavigationTypeFormResubmitted ){
        decisionHandler(WKNavigationActionPolicyAllow);
        return;
    }

AdblockRules

基本过滤规则

参考:AdblockPlus拦截规则简单教程

    • 通配符;
  1. @@表示例外规则符;
  2. 管道符 表示过滤规则终止;
  3. 双管道符   表示域名前匹配;
  4. 标记分隔符^表示单个分隔符的占位符。有时,您可能需要在过滤器中接受任何分隔符。分隔符可以是任何东西,除了一个字母,一个数字或以下情况之一:_,-,.,%。地址的末尾也可被视作一个分隔符。
  5. 感叹号!表示注释。!开头的行会被默认为注释行,不被执行。
  6. $表示过滤器选项;

规则库:EasyList

ad request 拦截原理
关键方法:e.preventDefault();

var filter = AdBlocker.checkFilterMatch(e.url, tagType, documentHost);
if(filter instanceof BlockingFilter) {
    e.preventDefault();
    ......

无图模式原理

js修改document加载行为

document.addEventListener("beforeload", ImageBlocker.blockImages, true);

/*blockImages beforeload*/
ImageBlocker.blockImages = function() {
    var isImage = event.url.match(/.jpg/i) || event.url.match(/.png/i) || event.url.match(/.gif/i) || event.url.match(/.jpeg/i) || event.url.match(/.bmp/i);
    if (isImage) {
        event.preventDefault();
    }
    var isImgTag = event.target.tagName == 'IMG';
    if (isImgTag) {
        event.preventDefault();
    }
}
//
/*替换background-image*/
ImageBlocker.removeBackgroundImages = function() {
    //alert('=====removeBackgroundImages')
    if (ImageBlocker.enable) {
        var bgImgs = document.body.querySelectorAll('*[style^=\"background-image:\"]');
        for (var j = 0; j < bgImgs.length; j++) {
            var bgImg = bgImgs[j];
            bgImg.style.backgroundImage = '';
        }
    };
}

Cookie注入两种方法

  1. swizzle loadRequest
    [WKWebView lwwk_swizzleMethod:@selector(loadRequest:) withMethod:@selector(myLoadRequest:)];
    

分iOS11以下与iOS11以上不同
iOS11以下,直接:

NSDictionary<NSString *, NSString *> *requestHeaderFields = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
        [mRequest setHTTPShouldHandleCookies:YES];
        [mRequest setAllHTTPHeaderFields:requestHeaderFields];

iOS11以上,要注意 setCookie:completionHandler:^{} 可能不会回调的bug;

  1. 使用js方法:使用 wkWebView evaluateJavaScript:@"document.cookie" 方法;