WKWebView交互
1.JS调OC
方案1:主要是通过拦截URL,做协议字符匹配(如:
js_native://alert
)
//需要先遵循WKNavigationDelegate协议
//在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURL *url = navigationAction.request.URL;
if ([[url absoluteString] hasSuffix:@"js_native://alert"]) {
[self handleJSMessage];
//不允许跳转
decisionHandler(WKNavigationActionPolicyAllow);
return;
}
//允许跳转
decisionHandler(WKNavigationActionPolicyAllow);
}
js部分代码
function jsCallNativeMethod(){
location.href = "js_native://alert";
}
方案2:WKScriptMessageHandler js方法名匹配 (如:
bf_jsCallNativeMethod
)
- (WKWebView *)webView {
if (!_webView) {
//网页配置文件
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc]init];
//允许与网页交互
configuration.selectionGranularity = YES;
configuration.userContentController = [WKUserContentController new];
WKPreferences *preferences = [WKPreferences new];
preferences.javaScriptCanOpenWindowsAutomatically = YES;
preferences.minimumFontSize = 50;
configuration.preferences = preferences;
configuration.userContentController = [WKUserContentController new];
[configuration.userContentController addScriptMessageHandler:self name:@"bf_jsCallNativeMethod"];
_webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:configuration];
_webView.navigationDelegate = self;
_webView.UIDelegate = self;
}
return _webView;
}
//遵循WKScriptMessageHandler协议
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"bf_jsCallNativeMethod"]) {
NSLog(@"这个是传过来的参数%@",message.body);
}
}
/*要记得销毁是移除*/
- (void)dealloc
{
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"bf_jsCallNativeMethod"];
}
js部分代码
function bf_jsCallNativeMethod() {
window.webkit.messageHandlers.bf_jsCallNativeMethod.postMessage('我的参数222');
}
方案3 主要是js中弹窗监听 比如: 警告框, 选择框, 输入框等监听
#pragma mark- WKUIDelegate
// WKUIDelegate是web界面中有弹出警告框时调用这个代理方法,主要是用来处理使用系统的弹框来替换JS中的一些弹框的,比如: 警告框, 选择框, 输入框等
/**
webView中弹出警告框时调用, 只能有一个按钮
@param webView webView
@param message 提示信息
@param frame 可用于区分哪个窗口调用的
@param completionHandler 警告框消失的时候调用, 回调给JS
*/
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
completionHandler();
}
// JavaScript调用confirm方法后回调的方法 confirm是js中的确定框,需要在block中把用户选择的情况传递进去
/** 对应js的confirm方法
webView中弹出选择框时调用, 两个按钮
@param webView webView description
@param message 提示信息
@param frame 可用于区分哪个窗口调用的
@param completionHandler 确认框消失的时候调用, 回调给JS, 参数为选择结果: YES or NO
*/
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
}
// JavaScript调用prompt方法后回调的方法 prompt是js中的输入框 需要在block中把用户输入的信息传入
/** 对应js的prompt方法
webView中弹出输入框时调用, 两个按钮 和 一个输入框
@param webView webView description
@param prompt 提示信息
@param defaultText 默认提示文本
@param frame 可用于区分哪个窗口调用的
@param completionHandler 输入框消失的时候调用, 回调给JS, 参数为输入的内容
*/
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"请输入" message:prompt preferredStyle:(UIAlertControllerStyleAlert)];
[alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.placeholder = @"请输入";
}];
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {
UITextField *tf = [alert.textFields firstObject];
completionHandler(tf.text);
}];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:(UIAlertActionStyleCancel) handler:^(UIAlertAction * _Nonnull action) {
completionHandler(defaultText);
}];
[alert addAction:ok];
[alert addAction:cancel];
[self presentViewController:alert animated:YES completion:nil];
}
2.OC调JS
调用苹果提供的API
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
使用方式
[_webView evaluateJavaScript:@"nativeCallbackJscMothod('123')" completionHandler:^(id _Nullable x, NSError * _Nullable error) {
NSLog(@"x = %@, error = %@", x, error.localizedDescription);
}];
JS部分
function nativeCallbackJscMothod(arguments) {
alert('原生调用js方法 传来的参数 = ' + arguments);
}
其他
#pragma mark- WKNavigationDelegate
/*
WKNavigationDelegate主要处理一些跳转、加载处理操作
*/
//页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
NSLog(@"----页面开始加载");
}
//当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
NSLog(@"----页面返回内容");
}
//页面加载完成时调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSLog(@"----页面加载完成");
// //原生回调JS
// [self.webView evaluateJavaScript:@"nativeCallbackJscMothod('我是回调')" completionHandler:^(id _Nullable s, NSError * _Nullable error) {
// NSLog(@"执行完成啦");
// }];
}
//页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"----页面加载失败");
}
//接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
NSLog(@"----接收到服务器跳转请求之后调用");
}
//在收到响应后,决定是否跳转
-(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
NSLog(@"%@",navigationResponse.response.URL.absoluteString);
//允许跳转
decisionHandler(WKNavigationResponsePolicyAllow);
//不允许跳转
//decisionHandler(WKNavigationResponsePolicyCancel);
}
//在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURL *url = navigationAction.request.URL;
if ([[url absoluteString] hasSuffix:@"js_native://alert"]) {
[self handleJSMessage];
//不允许跳转
decisionHandler(WKNavigationActionPolicyAllow);
return;
}
//允许跳转
decisionHandler(WKNavigationActionPolicyAllow);
}
/* 需要响应身份验证时调用,同样在block中需要传入用户身份凭证 */
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
//用户身份信息
NSLog(@"----需要响应身份验证时调用 同样在block中需要传入用户身份凭证");
NSURLCredential *newCard = [NSURLCredential credentialWithUser:@"" password:@"" persistence:NSURLCredentialPersistenceNone];
// 为 challenge 的发送方提供 credential
[[challenge sender] useCredential:newCard forAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeUseCredential,newCard);
}
/* 进程被终止时调用 */
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
NSLog(@"----进程被终止时调用");
}
/* 关闭webView时调用的方法 */
- (void)webViewDidClose:(WKWebView *)webView {
NSLog(@"----关闭webView时调用的方法");
}
后续继续整理更多方案
网友评论