推广

WKWebView使用与交互

iseeyu2年前 (2024-02-21)推广132

image.png

image.png

代理

遵守代理 navigationDelegate,主要处理一些跳转、加载处理操作
遵守代理 UIDelegate,主要处理JS脚本,确认框,警告框等

navigationDelegate

处理 跳转、加载等
代理方法也很多 简单讲几条

  • 身份验证 基本不用
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;

公司要对接一个第三方平台,然后就有了一个可奇葩的逻辑,用户填写完相关信息后,点击提交,然后服务器返回一个网页的源代码……需要用WebView加载这个网页。实现的时候发现,我自己写的简单的网页源码可以加载,但是服务器返回的就是无法加载。后来把源码保存成文件以后,用浏览器打开发现,该网页链接的站点是一个不受信任的站点,应该是因为服务器证书无效而不受信任。

- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
{
    NSLog(@"didReceiveAuthenticationChallenge");
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
        completionHandler(NSURLSessionAuthChallengeUseCredential,card);
    }
}
  • decidePolicyForNavigationAction、decidePolicyForNavigationResponse
    请求之前是否跳转、请求响应之后是否跳转(方法会多次调用的 因为跳转就有)
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction preferences:(WKWebpagePreferences *)preferences decisionHandler:(void (^)(WKNavigationActionPolicy, WKWebpagePreferences *))decisionHandler API_AVAILABLE(macos(10.15), ios(13.0));

2个方法任取其一

typedef NS_ENUM(NSInteger, WKNavigationActionPolicy) {
    WKNavigationActionPolicyCancel,
    WKNavigationActionPolicyAllow,
} API_AVAILABLE(macos(10.10), ios(8.0));

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSLog(@"decidePolicyForNavigationAction");
    decisionHandler(WKNavigationActionPolicyAllow);
}
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
    NSLog(@"decidePolicyForNavigationResponse");
    decisionHandler(WKNavigationResponsePolicyAllow);
}

WKNavigationActionPolicyAllow:网页可以正常跳转
WKNavigationActionPolicyCancel:取消网页跳转
此方法可以用于拦截url与web交互
获取协议、域名、完整路径、相对路径、端口、路径、search、参数
例子:

NSLog(@"scheme:%@",navigationAction.request.URL.scheme);
NSLog(@"host:%@",navigationAction.request.URL.host);
NSLog(@"absoluteString:%@",navigationAction.request.URL.absoluteString);
NSLog(@"relativePath:%@",navigationAction.request.URL.relativePath);
NSLog(@"port:%@",navigationAction.request.URL.port);
NSLog(@"path:%@",navigationAction.request.URL.path);
NSLog(@"pathComponents:%@",navigationAction.request.URL.pathComponents);
NSLog(@"query:%@",navigationAction.request.URL.query);
NSLog(@"decidePolicyForNavigationAction");

------ ViewController.m ------ 65 行 ------ scheme:https
------ ViewController.m ------ 66 行 ------ host:hqhhtest.hqhh520.cn
------ ViewController.m ------ 67 行 ------ absoluteString:https://hqhhtest.hqhh520.cn/h5/#/carRental?classId=9
------ ViewController.m ------ 68 行 ------ relativePath:/h5
------ ViewController.m ------ 69 行 ------ port:(null)
------ ViewController.m ------ 70 行 ------ path:/h5
------ ViewController.m ------ 71 行 ------ pathComponents:(
    "/",
    h5
)
------ ViewController.m ------ 72 行 ------ query:(null)

如果加载本地界面 不会主动调用action、response方法

  • 页面开始加载内容返回、加载完成加载失败*
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
    NSLog(@"didStartProvisionalNavigation");
}
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
{
    NSLog(@"didCommitNavigation");
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
    NSLog(@"didFinishNavigation");
}
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
    NSLog(@"didFailNavigation");
}
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
    //当Response响应后 不允许则会加载失败
    NSLog(@"didFailProvisionalNavigation");
}

UIDelegate

处理JS脚本,确认框,警告框等
js中加弹出框代码哦

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert];
    ];
    [self presentViewController:alert animated:YES completion:nil];
}

小功能

返回、前进上一个界面
if (self.webView.canGoBack) {
    [self.webView goBack];
}
if (self.webView.canGoForward) {
    [self.webView goForward];
}
获取标题、获取加载进度

记得销毁 dealloc 移除监听

[_webView removeObserver:self forKeyPath:@"title"];
[_webView removeObserver:self forKeyPath:@"estimatedProgress"];
[_webView.scrollView removeObserver:self forKeyPath:@"contentSize"];
- (void)addObserver
{
    [self.webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
    [self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:NULL];
    [self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    NSLog(@"keyPath:%@",keyPath);
    if ([keyPath isEqualToString:@"title"]) {
        self.title = self.webView.title;
    } else if ([keyPath isEqualToString:@"estimatedProgress"]) {
        NSLog(@"%f",self.webView.estimatedProgress);
    } else if ([keyPath isEqualToString:@"contentSize"]) {
        NSLog(@"%@",object);
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

交互

url重定向

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSLog(@"URL:%@",navigationAction.request.URL);
    decisionHandler(WKNavigationActionPolicyAllow);
}
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
    NSLog(@"decidePolicyForNavigationResponse");
    decisionHandler(WKNavigationResponsePolicyAllow);
}

判断url

MessageHandler(原生)

拓展点configuration、userContentController

初始化设置

- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
//设置偏好设置
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc]init];
// 默认是0 其实不建议在此设置的
config.preferences.minimumFontSize = 10;
// 是否支持javascript
config.preferences.javaScriptEnabled = YES;
//不通过用户交互,是否可以打开窗口
config.preferences.javaScriptCanOpenWindowsAutomatically = NO;
点击js原生响应

为了测试:本地准备好html文件 这里的js方法 和 三方
WebViewJavaScriptBridge写法略有不同哦
为了测试:本地准备好html文件 这里的js方法 和 三方WebViewJavaScriptBridge写法略有不同哦
为了测试:本地准备好html文件 这里的js方法 和 三方WebViewJavaScriptBridge写法略有不同哦

window.webkit.messageHandlers.<name>.postMessage(<messageBody>)

image.png

设置userContentController 遵守代理WKScriptMessageHandler 实现方法

WKUserContentController *userContentController = config.userContentController;
[userContentController addScriptMessageHandler:self name:@"showMobile"];
[userContentController addScriptMessageHandler:self name:@"showName"];
[userContentController addScriptMessageHandler:self name:@"showSendMsg"];

移除

WKUserContentController *controller = self.webView.configuration.userContentController;
[controller removeScriptMessageHandlerForName:@"showMobile"];
[controller removeScriptMessageHandlerForName:@"showName"];
[controller removeScriptMessageHandlerForName:@"showSendMsg"];

代理

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    NSLog(@"%@",message.body);
    NSLog(@"%@",message.name);
}
原生驱动js响应 evaluateJavaScript

可以编写几个按钮 去触发
js代码

image.png

[self.webView evaluateJavaScript:@"alertMobile()" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
    //JS 返回结果
    NSLog(@"%@ %@",response,error);
}];
[self.webView evaluateJavaScript:@"alertName('wpp')" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
    //JS 返回结果
    NSLog(@"%@ %@",response,error);
}];
[self.webView evaluateJavaScript:@"alertSendMsg('wpp','20岁')" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
    //JS 返回结果
    NSLog(@"%@ %@",response,error);
}];

WebViewJavascriptBridge(三方)

  • 单独准备html文件
  • 最好都是最新的库 旧的或许会崩溃
  • 设置minimumFontSize是40 不然界面控件有点小
  • 不能单独设置navigationDelegate代理 因为bridge需要设置该代理
  • 设置属性
#import "WebViewJavascriptBridge.h"
@property(nonatomic,strong)WebViewJavascriptBridge *bridge;
self.bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView];
[self.bridge setWebViewDelegate:self];
  • 设置监听的webView
- (void)addRegisterHandler
{
    [self.bridge registerHandler:@"scanClick" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@"扫一扫 %@",data);
        responseCallback(@"回调");
    }];
    [self.bridge registerHandler:@"locationClick" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@"地址 %@",data);
        responseCallback(@"回调");
    }];
    [self.bridge registerHandler:@"colorClick" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@"改变颜色 %@",data);
        responseCallback(@"回调");
    }];
    [self.bridge registerHandler:@"shareClick" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@"分享%@",data);
        responseCallback(@"回调");
    }];
    [self.bridge registerHandler:@"payClick" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@"支付 %@",data);
        responseCallback(@"回调");
    }];
    [self.bridge registerHandler:@"shakeClick" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@"摇一摇 %@",data);
        responseCallback(@"回调");
    }];
    [self.bridge registerHandler:@"goback" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@"返回 %@",data);
        responseCallback(@"回调");
    }];
}
  • js互动
[self.bridge callHandler:@"testJSFunction" data:@"一个字符串" responseCallback:^(id responseData) {
        NSLog(@"%@",responseData);
    }];

demo地址

小tip

预算view的高度

//避免高度不停回调
@property(nonatomic,assign)CGFloat webViewHeight;
//回调高度
@property(nonatomic,copy)void (^refreshUIBlock)(void);
if ([keyPath isEqualToString:@"contentSize"]) {
    if (self.webViewHeight == self.webView.scrollView.contentSize.height) {
        return;
    }
    self.webView.height = self.webView.scrollView.contentSize.height;
    self.height = self.webView.height;
    self.webViewHeight = self.webView.height;
    !self.refreshUIBlock ?: self.refreshUIBlock ();
    self.webViewHeight = self.webView.scrollView.contentSize.height;
}

进度条

显示不出来添加到scrollview
[self.webView.scrollView addSubview:self.progressView];

@property(nonatomic,strong)UIProgressView *progressView;

- (UIProgressView *)progressView
{
    if (!_progressView) {
        UIProgressView *view = [[UIProgressView alloc]initWithFrame:CGRectMake(0, 0, self.width, 0)];
        [self.webView addSubview:view];
        view.progressTintColor = kThemeColor;
        //view.trackTintColor = [UIColor lightGrayColor];
        _progressView = view;
    }
    return _progressView;
}

if ([keyPath isEqualToString:@"estimatedProgress"]) {
    //NSLog(@"%f",self.webView.estimatedProgress);
    [self.progressView setProgress:self.webView.estimatedProgress animated:YES];
    self.progressView.hidden = self.webView.estimatedProgress == 1.0 ? YES : NO;
}

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/57467.html

相关文章

正能量对于戒赌有没有帮助

正能量对于戒赌有没有帮助

有屁用。当今信息技术这么发达,咱们又是根正苗红的热血中国公民,社会上到处是正能量的人或事,咱们听少了还是见少了? 我刚进公司的时候组里有个比我早来3年的师傅。那工作之热情,待人之和睦,一度让我认为公司回到了国家刚刚改革开放时团结互助积极向上的时代。虽然后来事实证明...

如何写好一篇网络营销软文

如何写好一篇网络营销软文

软文是一种宣传文稿,目的是通过文字来传递信息和营销产品或服务。在上网络营销软文有着商业宣传和推销的特点,它既具有新闻的传播价值,又有商业广告的宣传价值。软文的目的在于引导读者对某个产品、服务或产生认知和好感,以达到的目的。写好网络营销软文软文需要以下几个步骤:1.明确目标受...

网络营销怎么做好策略。

网络营销怎么做好策略。

在中,除了后期实行,前期策略也很重要。一个好的策略影响到后期是否好执行。但是如何做好前期策略? 1、产品包装策略 通过对自身产品的了解在分析竞争对手,将产品进行包装。必须体现出自己产品和别人的与众不同。 2、网页策略 网站优化关键词优化,一看就知道要在页面上用心了,通过网页来运行自...

推送的暗黑模式:被 App 小红点淹没的你正被套路……

推送的暗黑模式:被 App 小红点淹没的你正被套路……

打开手机,数一数有多少 App 右上角有红色圆形数字?它们有没有干扰到你的日常生活?你会不会因此感到厌烦?)今天分享的这篇文章,将带你认识自带「暗黑模式」光环的推送通知,并通过几个案例一起来侃侃未来的发展 你有没有做过这样一个噩梦?梦里,你在许多红色圆形通知数字形成的海洋里溺水而亡……...

小编分享SEO优化中关键词布局有哪些技巧。

小编分享SEO优化中关键词布局有哪些技巧。

对于seo网站优化人员来说把做到首页就是重要的一步,网站有多个关键词词和很多的相关的关键词。我们要把这些平均发布到网站上。各位有没有经常在布置关键词的时候而烦恼, 下面给大家介绍下网站优化中关键词的技巧有哪些? ①、关键词竞赛太强,优化不上去。 ②、关键词的搜索量太少,网站没有流量。...

微信积分墙如何做,传统积分墙厂商的最后赌注?

微信积分墙如何做,传统积分墙厂商的最后赌注?

微信积分墙的留存比传统积分墙高一倍,上榜所需流量比传统积分墙少50%。本文详解微信积分墙的运营模式,常用作弊手段,防作弊措施,以及未来方向。   一微信积分墙诞生背景 回首2014年,从年初红红火火的ios积分墙的爆发,到年底的衰败,再到CP的不结算,扣...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片