推广

WKWebView使用与交互

iseeyu3年前 (2024-02-21)推广139

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

相关文章

西安企业做百度推广,一个月花三千和花三万到底差在哪?

4|最近跟几个西安的老板聊天,发现一个挺有意思的现象:同样做百度推广,有人一个月花三千块,询盘不断;有人一个月砸三万,水花都没见着。问他们区别在哪,大多数人说不清楚,只知道'钱花了,没效果'。 5| 6|百度推广这东西,说复杂也复杂,说简单也简单。核心就一件事:让你的潜在客户搜某个词的时候,你的信息...

我想当策划,大学应该选什么专业?

我想当策划,大学应该选什么专业?

学,广告,传播,公关,这些专业其实都可以。另外也可以学像汉语言文学,以及一些跟文学相关的一些专业,会对你找工作有帮助。但是,你想从事这个这份职业,除了专业的学习之外,更多的是,你要在上学的时候积极参与一些更营销策划相关的社会实践。比如说你可以做一些兼职,比如说帮别人去写稿,...

服装市场营销策略分析,“定位不慎满盘皆输”

服装市场营销策略分析,“定位不慎满盘皆输”

不同的区域需要不同的策略,而不同的营销策略需要不同的销售思路来配合。因此,在研究女装产品销售思路之前,最好先对于市场与营销策略做一次深入地了解。1.市场区域化(market segmentation):目标营销的第一步,是将整个市场拆分成若干个同性质的小市场。2.目标市场的...

晚间悦读丨你的思维方式,决定你的人生高度!

晚间悦读丨你的思维方式,决定你的人生高度!

越长大,越发现,能够决定你人生高度的,往往是你的认知层次。 你的认知在哪个层级,你的人生就处在什么状态。你认知的高度,决定了你人生的高度。 那如何才能升级方式、提升认知能力呢?可以从这三个方面做出改变。 NO. 1 改变态度 有人...

编写项目营销策划方案六大要点

编写项目营销策划方案六大要点

现在商业发展非常迅速,的需求非常的大,但是要做好营销策划是有一定难度的,我把自己做营销策划的一些体会在这里分享给朋友们。营销策划方案六大要点我们先说项目营销策划方案这个话题。大部分的营销策划人都是在企业里工作,大部分项目之初都是来源于一个想法,创始人、老板或者创始团队的一个...

【商场营销策划】如何进行商场营销策划?

【商场营销策划】如何进行商场营销策划?

商场是策划者们关注的永恒话题,那么究竟该如何作好商场营销策划呢?掌握以下这几点营销策略设计原则,至关重要!1.义利兼顾的原则。商场在获取利润的同时要充分考虑到消费者的合法利益和商场的长远利益。在作商场活动营销策略方案的时候应该将这一点作为首要的原则。对商场有利而对顾客不利的...

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

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