WKWebView使用遇到的一些坑,iOS中WKWebView的一些问

作者:新闻中心
  1. ATS的主题素材相近能影响webView内部网页的跳转

  2. 网页实现手势再次来到,自带的就有,只要张开设置

1.EvaluateJavaScript格局为异步

  • UIWebview:
    UIWebView中是同步施行的,间接调用
    - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
    艺术再次来到实行结果
  • WKWebView
    WKWebView中,改为了block的点子实行值重临,何况该办法的推行是异步的

延伸:奉行JS方法的施用处境之一,正是收获当前webview的title,WKWebView提供了新属性title,如若是想获取title,能够平昔运用WKWebView的title属性.

}

支持alert()

WKWebView默许不响应js的alert(卡塔尔国事件,怎么样能够开启alert权限呢?

代理WKUIDelegate方法

  • (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler

将会拿走到alert的音讯,不过不会弹出alert.

在情势内部

[alertController addAction:[UIAlertAction actionWithTitle:@"OK"

style:UIAlertActionStyleCancel

handler:^(UIAlertAction *action) {

completionHandler();

}]];

if ([self.delegate isKindOfClass:[UIViewController class]]) {

UIViewController *controller = (UIViewController *)self.delegate;

[controller presentViewController:alertController animated:YES completion:^{}];

}

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { // 此代理中实现这个 解决网页某些点击不跳转的问题 if navigationAction.targetFrame == nil { webView.load(navigationAction.request) } // 判断 request的类型 let requestType = navigationAction.navigationType switch requestType { case .backForward: print("backForward") case .formResubmitted: print("formResubmitted") case .formSubmitted: print("formSubmitted") case .linkActivated: print("linkActivated") case .reload: print case .other: print } decisionHandler }

3.不走 NSUPAJEROLProtocol, 不能够自定义网络央求.

打开ituns.apple.com跳转到appStore, 拨打电话, 唤起邮箱等一密密层层操作UIWebView暗中认可扶植的.

区别

1.Cache 与系统分离,何况在 iOS8地方不可能清除(iOS9日增了连带措施卡塔尔

####2.WKWebView私下认可禁止了一部分跳转

3.WKWebView默认禁止了部分跳转

  • UIWebView

开荒ituns.apple.com跳转到appStore, 拨打电话, 唤起邮箱等一文山会海操作UIWebView默许帮助的.

  • WKWebView

暗中认可禁绝了上述作为,除此而外,js端通过window.open()展开新的网页的动作也被禁掉了.

哪些辅助吧?

//懒加载吧
- (WKWebView *)wkWebView{
    if (!_wkWebView) {
 ///--------------------------把 cookiesManager 做成单例模式,每一个需要同步的 WKWebview 都设置这个 processPool.
        WKCookieSyncManager *cookiesManager = [WKCookieSyncManager sharedWKCookieSyncManager];
        //设置网页的配置文件
        WKWebViewConfiguration * Configuration = [[WKWebViewConfiguration alloc]init];
//允许视频播放
        Configuration.allowsAirPlayForMediaPlayback = YES;
        // 允许在线播放
        Configuration.allowsInlineMediaPlayback = YES;
// 允许可以与网页交互,选择视图
        Configuration.selectionGranularity = YES;
/// -------------------------web内容处理池,设置这个processPool
        Configuration.processPool = cookiesManager.processPool;
        //自定义配置,一般用于 js调用oc方法(OC拦截URL中的数据做自定义操作)
        WKUserContentController * UserContentController = [[WKUserContentController alloc]init];


        // 是否支持记忆读取
        Configuration.suppressesIncrementalRendering = YES;
        // 允许用户更改网页的设置
        Configuration.userContentController = UserContentController;
        _wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 10, 100,100) configuration:Configuration];

//添加到主控制器上
        [self.view addSubview:self.wkWebView];
        [self webViewloadURLType];//加载的代码(比如下面两行)
//创建一个NSURLRequest 的对象
 //NSURLRequest * inforURL = [NSURLRequest requestWithURL:[NSURL URLWithString:selfURL] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15];////selfURL为登陆后的URl
//加载网页
//[self.wkWebView loadRequest:inforURL];



        // 设置代理
        _wkWebView.navigationDelegate = self;
        _wkWebView.UIDelegate = self;

        //开启手势触摸
        _wkWebView.allowsBackForwardNavigationGestures = YES;
        // 设置 可以前进 和 后退
        //适应你设定的尺寸
        [_wkWebView sizeToFit];
    }
    return _wkWebView;
}

在转换此前,需求先来探讨一番,到底适不相符替换. 

1.EvaluateJavaScript艺术为异步

  • UIWebview:

UIWebView中是同步施行的,直接调用

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;```

方法返回执行结果

- WKWebView

在```WKWebView```中,改为了```block```的方式进行值返回,并且该方法的执行是异步的

```- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ __nullable)(__nullable id, NSError * __nullable error))completionHandler;

延长:施行JS方法的应用景况之一,便是获取当前webview的title,WKWebView提供了新属性title,假若是想博得title,能够一向接收WKWebView的title属性.

区别

UIApplication *app = [UIApplication sharedApplication];

简介

应用WKWebView一段时间,发掘它和UIWebView的有的区分之处,有一写遭受的坑,今后对管理形式做了个小总结,现分享给大家.

  1. 清除WKWebview的缓存

if (!navigationAction.targetFrame.isMainFrame) {

2.cookie装置方法差别

  • UIWebView:

经过该办法设置的,为大局的cookie,项目中放肆的UIWebView均辅导相近的cookie.设置之后无需做额外的操作.

  • WKWebView

网页将不再能取得暗中认可的cookie,假使急需指点cookie,必要做一些操作:

1 初始化cookie, NSString *cookie = @"document.cookie='cookieKey=cookieValue'";

2 注入cookie

收获当前的userContentController澳门新葡京平台游戏,:

注入scrpit:

WKUserScript *script = [[WKUserScript alloc] initWithSource:cookieValue injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];

[userContentController addUserScript:script];

private func clearWKWebViewCache() { // iOS9开始提供了清理WKWebView的API let version = UIDevice.current.systemVersion guard let aVersion = Double, aVersion > 9.0 else { return } let websiteDataTypes = Set([WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache, WKWebsiteDataTypeOfflineWebApplicationCache, WKWebsiteDataTypeCookies, WKWebsiteDataTypeSessionStorage, WKWebsiteDataTypeLocalStorage, WKWebsiteDataTypeWebSQLDatabases, WKWebsiteDataTypeIndexedDBDatabases]) let date = Date(timeIntervalSince1970: 0) WKWebsiteDataStore.default().removeData(ofTypes: websiteDataTypes, modifiedSince: date, completionHandler: {}) }

简介

动用WKWebView一段时间,发掘它和UIWebView的一些有别于之处,有一写遭遇的坑,今后对管理格局做了个小总括,现分享给我们.

function _createQueueReadyIframe(doc) {n

注意

流入script时参数indectionTime有五个可筛选WKUserScriptInjectionTimeAtDocumentStartWKUserScriptInjectionTimeAtDocumentEnd,

咱俩看一下官方文书档案对于那多少个筛选的分解:

WKUserScriptInjectionTimeAtDocumentStart : 注入机缘为document的因素生成之后,其余剧情load以前.

WKUserScriptInjectionTimeAtDocumentEnd : 注入机会为document全体load实现,放肆子财富load完毕以前.

貌似情形下,假使想不久注入cookie,在WKUserScriptInjectionTimeAtDocumentStart时形成就可以,但是有一种奇特情状,即近期的治疗圈为后端渲染,数据央浼注重cookie中的sessionKey,而前面多个页面包车型客车要素信赖后端再次来到的数目,由此,有三个难题,即cookie是在页面成分生成之后流入的,而在此此前,后端必要得到cookie,那么应该怎么做吧??

// 一直为 falsewebView.canGoBack// 执行无效果webView.goBack()

可是 WKWebview 有几个很坑的难点

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler

支持window.open()

须要开采新分界面是,WKWebView的代理WKUIDelegate方法

  • (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures

会堵住到window.open(State of Qatar事件.

只须求大家在在方法内开展拍卖

if (!navigationAction.targetFrame.isMainFrame) {

[webView loadRequest:navigationAction.request];

}

UIApplication.shared.open

2.库克ie 与系统一分配离,web 的 cookie 与native 的 cookie 是分离的.

messagingIframe.src = CUSTOM_PROTOCOL_SCHEME '://' QUEUE_HAS_MESSAGEn

在requestHeader内注入cookie

NSString *cookie = @"cookieKey1=cookieValue1;cookieKey2=cookieValue2";

 [mutableRequest addValue:cookie forHTTPHeaderField:@"Cookie"];

如此那般在互联网央求开始时,requestHeader将指引cookie.

小德姆o的链接请点击 WKWebView的德姆o

2.cookie设置方法各异

  • UIWebView:

由此该方式设置的,为大局的cookie,项目中率性的UIWebView均教导同样的cookie.设置之后不须求做额外的操作.

  • WKWebView
    网页将不再能博取私下认可的cookie,如若急需指导cookie,须求做一些操作:
    1 初始化cookie, NSString *cookie = @"document.cookie='cookieKey=cookieValue'";
    2 注入cookie
    赢伏贴前的userContentController:

注入scrpit:
WKUserScript *script = [[WKUserScript alloc] initWithSource:cookieValue injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[userContentController addUserScript:script];


能够跳转appStore也许拨号

-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

if(webView != self.wkWebView) {

decisionHandler(WKNavigationActionPolicyAllow);

return;

}

UIApplication *app = [UIApplication sharedApplication];

if ([url.scheme isEqualToString:@"tel"])

{

if ([app canOpenURL:url])

{

[app openURL:url];

decisionHandler(WKNavigationActionPolicyCancel);

return;

}

}

if ([url.absoluteString containsString:@"ituns.apple.com"])

{

if ([app canOpenURL:url])

{

[app openURL:url];

decisionHandler(WKNavigationActionPolicyCancel);

return;

}

}

decisionHandler(WKNavigationActionPolicyAllow);

}

  1. WKWebView须要在这里代理方法中写入如下代码工夫兑现网页间的跳转,不然点击大概未有效应(判别request类型也在这里代理中)
注意

流入script时参数indectionTime有七个可筛选WKUserScriptInjectionTimeAtDocumentStartWKUserScriptInjectionTimeAtDocumentEnd,
咱俩看一下官方文书档案对于那多少个筛选的疏解:
WKUserScriptInjectionTimeAtDocumentStart : 注入时机为document的因素生成之后,别的剧情load在此之前.
WKUserScriptInjectionTimeAtDocumentEnd : 注入时机为document全体load达成,率天性能源load实现此前.
貌似情状下,借使想不久注入cookie,在WKUserScriptInjectionTimeAtDocumentStart时变成就能够,不过有一种新鲜情状,即前段时间的医疗圈为后端渲染,数据乞请重视cookie中的sessionKey,而前面二个页面的要素信赖后端重临的数额,由此,有三个难题,即cookie是在页面成分生成之后流入的,而在这里早前,后端需求获得cookie,那么应该如何做吧??

var iFrame;

WKWebView使用境遇的坑

这些比较轻便管理,让五个 webview 使用同三个 WKProcesspool 就足以了.

if ([self.delegate isKindOfClass:[UIViewController class]]) {

  1. webView和网页JS的人机联作作者用的是第三方webViewJavascriptBridge,须要网页端在JS中也要注入部分代码技巧落到实处互调(原生的相通不用,也丰富不难)

  2. 网页端今后有二个名称叫 单页面的本事,iOS中的webView加载此类页面中的页面跳转时,代理方法不走,何况回去和判别失效

3.WKWebView默许禁绝了部分跳转

  • UIWebView
    开拓ituns.apple.com跳转到appStore, 拨打电话, 唤起邮箱等一连串操作UIWebView默许扶助的.
  • WKWebView
    私下认可禁绝了以上行为,除此而外,js端通过window.open()开辟新的网页的动作也被禁掉了.
    怎么支撑吧?

- WKWebView

webView.allowsBackForwardNavigationGestures = true

运用(在开立wkwebview的时候,其实就两句在横线处标记啦):


  1. WKWebView中也得以用如下的主意调起safari来开荒网页
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }])];
    [self presentViewController:alertController animated:YES completion:nil];

}
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
    //    DLOG(@"msg = %@ frmae = %@",message,frame);
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
    }])];
    [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
}
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.text = defaultText;
    }];
    [alertController addAction:([UIAlertAction actionWithTitle:@"完成" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(alertController.textFields[0].text?:@"");
    }])];


    [self presentViewController:alertController animated:YES completion:nil];
}

var QUEUE_HAS_MESSAGE = '__WVJB_QUEUE_MESSAGE__'n

======================alert不弹出===========================================
WKWebView暗中同意不响应js的alert(State of Qatar事件,如何能够开启alert权限呢?
设置wkwebview.delegate = self;
福寿无疆上面多个办法:
onJsAlert :警报框(WebView上alert无效,供给定制WebChromeClient管理弹出卡塔尔(قطر‎
onJsConfirm : 确定框.
onJsPrompt : 提示框.

return;

  1. 至于cookies的问题。UIWebView走的是大局的http库克ieStrorage,然而WKWebView不是。WKWebView仍旧供给先安装全局的cookie然后转成其JS的格式再流入。

同叁个app中,多个页面使用wkwebview,在二个页面签到,其他页面没有须求再登陆,由于选择wkwebview其cookie不一致步,所以会鬼使神差在多少个页面签到后还需在另四个页面重新登入的情景。上代码吧!
小心:注意:注意:所加载页面必得为【登入后】的页面。


So, 要求 native 与 web 统一 cookie 就无法聊起了,以至 webview 于 webview 之间的 cookie 同步也格外.

}

#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>

@interface WKCookieSyncManager : NSObject

@property (nonatomic, strong) WKProcessPool *processPool;

- (void)setCookie;

  (instancetype)sharedWKCookieSyncManager;

@end

messagingIframe.style.display = 'none'n

支持window.open()

内需开采新分界面是,WKWebView的代办WKUIDelegate方法

  • (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
    会阻碍到window.open(卡塔尔事件.
    只须要大家在在方法内进行管理
    if (!navigationAction.targetFrame.isMainFrame) {
    [webView loadRequest:navigationAction.request];
    }

================wkWebview==========================
村办所遇到的多少个难点记录:
1.cookie难题(三种管理格局,例如新建单例类)。
2.点击内部链接无反应难题。
3.点击不弹出js的alert(卡塔尔。
4.AFNetworking存取cookie。
5.双击某处闪退难题。
6.点击要下载的文件不能下载,跳转到Safari管理。
7.人机联作的其他主题素材。

3.不弹出题目

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }])];
    [self presentViewController:alertController animated:YES completion:nil];

}
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
    //    DLOG(@"msg = %@ frmae = %@",message,frame);
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
    }])];
    [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
}
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.text = defaultText;
    }];
    [alertController addAction:([UIAlertAction actionWithTitle:@"完成" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(alertController.textFields[0].text?:@"");
    }])];


    [self presentViewController:alertController animated:YES completion:nil];
}

======================其他===========================
呈现二个网页,可是急需掩盖一部分页面

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

    // 在HTML标签都加载完成后,开始处理HTML标签,调用JS,操作document
    //移除网页中的footer。
//    NSString *doc = @"document.getElementById('footer').remove();";
//    [self.wkWebView evaluateJavaScript:doc
//                     completionHandler:^(id _Nullable htmlStr, NSError * _Nullable error) {
//                         if (error) {
//                             NSLog(@"JSError----:%@",error);
//                         }
//                         NSLog(@"html----:%@",htmlStr);
//                     }] ;


    //解决长按tabbaritem弹出alert问题。
//    NSString *changAnAlertQ = @"document.documentElement.style.webkitTouchCallout='none';";
//    [webView evaluateJavaScript:changAnAlertQ completionHandler:^(id _Nullable htmlStr, NSError * _Nullable error) {
//
//    }];
}

WKWebView再次来到某些历史页面

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
//WKWebView返回某个历史页面
    if (navigationAction.navigationType==WKNavigationTypeBackForward) {
        //判断是返回类型
        if (webView.backForwardList.backList.count>0) {
            //得到栈里面的list
            WKBackForwardListItem * item = webView.backForwardList.currentItem;
            //得到现在加载的list
            for (WKBackForwardListItem * backItem in webView.backForwardList.backList) {
                //循环遍历,得到你想退出到 webView.backForwardList.backList[0]
                //添加判断条件
                [webView goToBackForwardListItem:backItem];
            }
        }
    }
decisionHandler(WKNavigationActionPolicyAllow);

}

=================================================
来源(cookie):http://blog.csdn.net/ccwf2006/article/details/53173489
来源(alert):http://www.cnblogs.com/n1ckyxu/p/5587722.html
http://blog.csdn.net/j_av_a/article/details/52160413
除此以外:webview的离线缓存参谋http://blog.csdn.net/horisea/article/details/53815596(不适用于WKWebview)。

[userContentController addUserScript:script];

#import "WKCookieSyncManager.h"

@interface WKCookieSyncManager () <WKNavigationDelegate>
@property (nonatomic, strong) WKWebView *webView;
///用来测试的url这个url是不存在的
@property (nonatomic, strong) NSURL *testUrl;
@end
@implementation WKCookieSyncManager

  (instancetype)sharedWKCookieSyncManager {
    static WKCookieSyncManager *sharedWKCookieSyncManagerInstance = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        sharedWKCookieSyncManagerInstance = [[self alloc] init];
    });
    return sharedWKCookieSyncManagerInstance;
}
- (void)setCookie {
    //判断系统是否支持wkWebView
    Class wkWebView = NSClassFromString(@"WKWebView");
    if (!wkWebView) {
        return;
    }
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    config.processPool = self.processPool;
    self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:self.testUrl];
    self.webView.navigationDelegate = self;
    [self.webView loadRequest:request];
}

#pragma - get
- (WKProcessPool *)processPool {
    if (!_processPool) {
        static dispatch_once_t predicate;
        dispatch_once(&predicate, ^{
            _processPool = [[WKProcessPool alloc] init];
        });
    }
    return _processPool;
}
- (NSURL *)testUrl {
    if (!_testUrl) {
        NSURLComponents *urlComponents = [NSURLComponents new];
        urlComponents.host = @"oam.yixiangdai.com";
        urlComponents.scheme = @"http";
        urlComponents.path = @"/tsttsssdsds.aspx";
        NSLog(@"测试url=%@", urlComponents.URL);
        //一个不存在 的URl
        return urlComponents.URL;
    }
      return _testUrl;
}

//交互js(略过)
#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    //取出cookie
    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    //js函数
    NSString *JSFuncString =
    @"function setCookie(name,value,expires)
    {
        var oDate=new Date();
        oDate.setDate(oDate.getDate() expires);
        document.cookie=name '=' value ';expires=' oDate;
    }
    function getCookie(name)
    {
        var arr = document.cookie.match(new RegExp('(^| )' name '=([^;]*)(;|$)'));
        if(arr != null) return unescape(arr[2]); return null;
    }
    function delCookie(name)
    {
        var exp = new Date();
        exp.setTime(exp.getTime() - 1);
        var cval=getCookie(name);
        if(cval!=null) document.cookie= name   '=' cval ';expires=' exp.toGMTString();
    }";

    //拼凑js字符串
    NSMutableString *JSCookieString = JSFuncString.mutableCopy;
    for (NSHTTPCookie *cookie in cookieStorage.cookies) {
        NSString *excuteJSString = [NSString stringWithFormat:@"setCookie('%@', '%@', 1);", cookie.name, cookie.value];
        [JSCookieString appendString:excuteJSString];
        NSLog(@"----%@",excuteJSString);
    }
    //执行js
    [webView evaluateJavaScript:JSCookieString completionHandler:nil];
}

大家看一下法定文书档案对于这三个选项的演讲:

能够跳转appStore可能拨号

-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
if(webView != self.wkWebView) {
decisionHandler(WKNavigationActionPolicyAllow);
return;
}
UIApplication *app = [UIApplication sharedApplication];
if ([url.scheme isEqualToString:@"tel"])
{
if ([app canOpenURL:url])
{
[app openURL:url];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
if ([url.absoluteString containsString:@"ituns.apple.com"])
{
if ([app canOpenURL:url])
{
[app openURL:url];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
decisionHandler(WKNavigationActionPolicyAllow);
}


WKWebView使用碰着的坑

急需专一的是:


WKWebView 拦截URL

在requestHeader内注入cookie

NSString *cookie = @"cookieKey1=cookieValue1;cookieKey2=cookieValue2";

这么在互连网哀告起首时,requestHeader将引导cookie.

```WKUserScriptInjectionTimeAtDocumentStart``` : 注入机会为document的成分生成之后,其余内容load在此之前.

要是运用多个以上 webview 同不平日间做客服务器,那八个 webview 之间的存款和储蓄是毫非亲非故系的.最入眼的是,保存登入意况的 sessionid 也分裂等,也正是说,在四个 webview 页面里登入之后,另三个 webview 依然是未登入的状态.

{

====================相比UIwebview及此外坑=============

}

一.先来化解 webview 与 webview 之间的一路难题.

{

.m

}

======================cookie===========================================
iOS8 以往分娩了 WKWebview,呈现更加快作用越来越高.

}]];

始建单例类.h

UIViewController *controller = (UIViewController *)self.delegate;

```

######支持alert()

```

{

}

【进级篇】iOS使用WKWebView混编开垦

 这个  上一篇  中,还会有一段代码,是 JS 加载UHavalL的.   跟下面 我们项目中 嵌入的JS相仿.

WKWebView 那些坑 

var CUSTOM_PROTOCOL_SCHEME = 'wvjbscheme'n

只必要我们在在方法内进行拍卖

iFrame = document.createElement("iframe");

代理```WKUIDelegate```方法

那是找来的或然遇见的各路坑的情状:

WKWebView-Bridge 在react-native封装的兑现 iOS开采

}

这么在网络诉求开头时,requestHeader将指点cookie.

-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

functionloadURL(url){

document.body.appendChild(iFrame);

doc.documentElement.appendChild(messagingIframe)n

}

1.借使完毕了这几个代理方法,就非得得调用decisionHandler这些block,不然会促成app 崩溃。block参数是个枚举类型,WKNavigationActionPolicyCancel代表撤消加载,也正是UIWebView的代办方法return NO的事态;WKNavigationActionPolicyAllow代表允许加载,也便是UIWebView的代理方法中 return YES的处境。

######在requestHeader内注入cookie

注入scrpit:

handler:^(UIAlertAction *action) {

if ([url.absoluteString containsString:@"ituns.apple.com"])

关于UIWebView的总结

iFrame.parentNode.removeChild(iFrame);

[app openURL:url];


暗中同意禁绝了上述作为,除了那么些之外,js端通过```window.open()```开拓新的网页的动作也被禁掉了.

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures

选用WKNavigationDelegate中的代理方法,拦截自定义的UCR-VL来得以完毕JS调用OC方法。

#WKWebView使用境遇的坑

(17.8.16)后记:

[controller presentViewController:alertController animated:YES completion:^{}];

貌似情形下,要是想尽快注入cookie,在```WKUserScriptInjectionTimeAtDocumentStart```时成功就可以,然则有一种非常情状,即当前的治病圈为后端渲染,数据伏乞信任cookie中的```sessionKey```,而前面三个页面包车型大巴要素信任后端再次回到的数额,因而,有一个难点,即cookie是在页面成分生成之后流入的,而在这里前面,后端须求得到cookie,那么应该咋办呢??

#pragma mark - WKNavigationDelegate

iOS下JS与OC相互调用(三)--MessageHandler

在章程内部

}

品类中放到了一段JS代码,其中有这般一段,功效是  "使用JS加载UKugaL", 然后在webview中拦截U凯雷德L,进而起到 "JS调用原生' 的效用.


```        WKUserContentController *userContentController = self.wkWebView.configuration.userContentController;

}n

####1.cookie安装方法分化

```

```

if ([app canOpenURL:url])

iOS下JS与OC相互调用(七)--Cordova底子

```[storage setCookie:cookieKey value:cookieValue];

NSString *scheme = [URL scheme];

[app openURL:url];

  WKWebView使用境遇的坑    

{

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler


if(webView != self.wkWebView) {

{

return;

iOS下JS与OC相互调用(一)--UIWebView 拦截U帕杰罗L

messagingIframe = doc.createElement('iframe')n

iFrame.setAttribute("src", url);

选用WKWebView一段时间,发掘它和UIWebView的局地组别之处,还恐怕有局地蒙受的坑

function _doSend(message, responseCallback) {n

decisionHandler(WKNavigationActionPolicyCancel);

1 初始化cookie, ```NSString *cookie =  @"document.cookie='cookieKey=cookieValue'";```

}

iOS下JS与OC相互调用(四)--JavaScriptCore

会阻止到window.open(卡塔尔(قطر‎事件.

- UIWebView:

iFrame.setAttribute("width","0px");

看WKWebView是还是不是坑太多,根本不能够使用.

- WKWebView

iFrame.setAttribute("height","0px");

WKUserScript *script = [[WKUserScript alloc] initWithSource:cookieValue injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];

decisionHandler(WKNavigationActionPolicyCancel);

透过该方式设置的,为大局的cookie,项目中随便的```UIWebView```均指导同样的cookie.设置之后无需做额外的操作.

WKWebView 拦截URL   ----那一个清除了自个儿的主题材料  

流入script时参数indection提姆e有七个可采取```WKUserScriptInjectionTimeAtDocumentStart```和```WKUserScriptInjectionTimeAtDocumentEnd```,

网页将不再能博得暗中同意的cookie,如果供给指引cookie,要求做一些操作:

decisionHandler(WKNavigationActionPolicyCancel);

什么样支撑啊?

completionHandler();

######支持window.open()

- UIWebView

iOS下JS与OC互相调用(二)--WKWebView 拦截ULANDL

关键是要替换WebViewJavascriptBridge中,使用到的UIWebView的代理方法.在轮流进程中,有个难点卡了十分久.

iFrame = null;

iFrame.setAttribute("frameborder","0");

}n

UIWebView和WKWebView的应用及js交互作用 

```WKUserScriptInjectionTimeAtDocumentEnd``` : 注入机会为document全部load实现,任脾性财富load实现在此之前.

拦截URL

decisionHandler(WKNavigationActionPolicyAllow);

(使用材质:

}

iFrame.setAttribute("style","display:none;");

那是找来的大概可参看的 使用材料:

[alertController addAction:[UIAlertAction actionWithTitle:@"OK"

if ([scheme isEqualToString:@"haleyaction"]) {

if ([url.scheme isEqualToString:@"tel"])

decisionHandler(WKNavigationActionPolicyAllow);

[webView loadRequest:navigationAction.request];

亟待开垦新分界面是,WKWebView的代办```WKUIDelegate```方法

return;

######注意

品种中UIWebView和协同的使用的WebViewJavascriptBridge 都以比较久此前封装的,WebViewJavascriptBridge中代码跟web端的代码有耦合.所以不能够弃用.也不可能运用英特网现存的WebViewJavascriptBridge库. 只可以去看WebViewJavascriptBridge中须要改良的地点.

跟JS打交道多了. 也只顾了下JS相关的.

2 注入cookie

这是上边援引的有个别博主的连串,有亟待能够看一下

NSURL *URL = navigationAction.request.URL; //在这里拦截的URL

iOS下JS与OC相互调用(八)--Cordova精解 实战

######能够跳转appStore或许拨号

decisionHandler(WKNavigationActionPolicyAllow);

// 发起号召后那些iFrame就没用了,所以把它从dom上移除掉

WKWebView暗中认可制止了有的跳转 

```    [mutableRequest addValue:cookie forHTTPHeaderField:@"Cookie"];

2.别样的有关为啥要统一设置scheme,在上一篇中讲过。

JS的Document属性和艺术小结 

var messagingIframen

[self handleCustomAction:URL];

iOS下JS与OC相互调用(五)--UIWebView WebViewJavascriptBridge

return;

赢稳当前的```userContentController```:

将会获取到alert的音讯,可是不会弹出alert.

}

style:UIAlertActionStyleCancel

iOS下JS与OC相互调用(六)--WKWebView WebViewJavascriptBridge

if ([app canOpenURL:url])

```NSString *cookie =  @"cookieKey1=cookieValue1;cookieKey2=cookieValue2";```

WKWebView私下认可不响应js的alert(卡塔尔国事件,如何能够开启alert权限呢?

```NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];

自己项目中实际上替换遭受的主题素材:

本文由新葡京8455发布,转载请注明来源

关键词: