美文网首页iOS精華
iOS WKWebView与JS交互

iOS WKWebView与JS交互

作者: 小白进城 | 来源:发表于2017-12-25 11:04 被阅读117次

用户操作交互

就是截获JS调用alert、confirm、prompt函数,来使用原生控件实现样式及操作,并将用户操作回调给JS

代理:WKUIDelegate

具体步骤:

1、设置代理

webView.UIDelegate = self;

2、完成代理方法

部分代理方法

// 在JS端调用alert函数时,会触发此代理方法。
// JS端调用alert时所传的数据可以通过message拿到
// 在原生得到结果后,需要回调JS,是通过completionHandler回调
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;

// JS端调用confirm函数时,会触发此方法
// 通过message可以拿到JS端所传的数据
// 在iOS端显示原生alert得到YES/NO后
// 通过completionHandler回调给JS端
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler;

// JS端调用prompt函数时,会触发此方法
// 要求输入一段文本
// 在原生输入得到文本内容后,通过completionHandler回调给JS
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;

演示:

演示

自定义方法

就是截获JS调用自定义方法,实现某些功能

代理:WKScriptMessageHandler

具体步骤:

1、注册方法

[webView.configuration.userContentController addScriptMessageHandler:self name:@"copyWeiXinHao"];   // 复制微信号
[webView.configuration.userContentController addScriptMessageHandler:self name:@"goToWeiXinApp"];   // 跳转微信App
[webView.configuration.userContentController addScriptMessageHandler:self name:@"getCurrentContent"];   // 获取原生剪切板内容

2、实现WKScriptMessageHandler方法、注册的方法

// message.name为方法名
// message.body为js传递的参数,是个id类型
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    if ([message.name isEqualToString:@"copyWeiXinHao"]) {
        NSString *wxh = message.body;
        NSLog(@"微信号:%@",wxh);
        [self copyWeiXinHao:wxh];
    }
    else if ([message.name isEqualToString:@"getCurrentContent"]) {
        NSString *content = [self getCurrentContent];
        NSString *promptCode = [NSString stringWithFormat:@"getCurrentWeiXinHao(\"%@\")",content];
        // OC传递数据给JS
        [self.webView.webView evaluateJavaScript:promptCode completionHandler:^(id _Nullable response, NSError * _Nullable error) {
        }];
    }
    else if ([message.name isEqualToString:@"goToWeiXinApp"]) {
        [self goToWeiXinApp];
    }
}
// 复制微信号
-(void)copyWeiXinHao:(NSString *)wxh{
    [[UIPasteboard generalPasteboard] setString:wxh];
}
// 当前剪切板信息
-(NSString*)getCurrentContent{
    return [[UIPasteboard generalPasteboard] string];
}
// 跳转微信应用
-(void)goToWeiXinApp{
    NSURL *url = [NSURL URLWithString:@"weixin://"];
    BOOL canOpen = [[UIApplication sharedApplication] canOpenURL:url];
    if (canOpen){   //打开微信
        [[UIApplication sharedApplication] openURL:url];
    }else {
        NSLog(@"您的设备尚未安装微信");
    }
}

3、移除监听

-(void)dealloc{
    // 根据name移除
    [self.webView.webView.configuration.userContentController removeScriptMessageHandlerForName:@"copyWeiXinHao"];
//    [self.webView.webView.configuration.userContentController removeAllUserScripts]; // 移除所有
}

补充:

1、JS传递OC

function 方法名() {
    window.webkit.messageHandlers.方法名.postMessage('参数');
}

2、OC传递JS

[webView evaluateJavaScript:@"方法名(参数)" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
}];

演示:

演示

补充:JS文件


<!doctype html>
<html>
    <head>
        <meta charset="UTF-8">
            
            <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, target-densitydpi=device-dpi"/>
            
            <title>JSCallOC</title>
            
            <style>
                *
                {
                    //-webkit-tap-highlight-color: rgba(0,0,0,0);
                    text-decoration: none;
                }
            
            html,body
            {
                -webkit-touch-callout: none;                /* prevent callout to copy image, etc when tap to hold */
                -webkit-text-size-adjust: none;             /* prevent webkit from resizing text to fit */
                -webkit-user-select: none;                  /* prevent copy paste, to allow, change 'none' to 'text' */
            }
            
            #div-a
            {
                background:#FBA;
                color:#FFF;
                
                border-radius: 25px 5px;
            }
            
            
                </style>
            
            </head>
    
    <body style="background:#CDE; color:#FFF">
        
        
        <div id="div-a">
            <center>
                <br/>

                <input type="button" value=alert onclick="alert('禁止操作');" />
                <br/>
                <br/>


                <input type="button" value="confirm" onclick="confirm('确定提交吗?');" />
                <br/>
                <br/>


                <input type="button" value="prompt" onclick="prompt('请输入姓名');" />
                <br/>
                <br/>


                <input type="button" value="复制微信号" onclick="copyWeiXinHao();" />
                <br/>
                <br/>
                
                
                <input type="button" value="跳转微信" onclick="goToWeiXinApp();" />
                <br/>
                <br/>
                
                <input type="button" value="获取应用剪切板内容" onclick="getCurrentContent();" />
                <br/>
                <br/>
                
                <a id="push" href="#" onclick="">
                    xxx
                </a>
                
            </center>
        </div>
        
        
        <script type="text/javascript">
            
            function copyWeiXinHao() {
                window.webkit.messageHandlers.copyWeiXinHao.postMessage('476512340');
            }
        
            function goToWeiXinApp() {
                window.webkit.messageHandlers.goToWeiXinApp.postMessage('');
            }
            
            function getCurrentContent() {
                window.webkit.messageHandlers.getCurrentContent.postMessage('');
            }
        
            function getCurrentWeiXinHao(wxh) {
                document.getElementById('push').innerText = wxh;
            }
        
            </script>
        
    </body>
    
</html>


demo演示地址


⚠️ 坑:

1、WKWebView执行js代码,要先被加载到父视图上

2、关于不能释放问题的解决方案

思路:另外创建一个弱引用代理对象,然后通过代理对象回调指定的self

.h 文件

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

@interface WeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>

@property (nonatomic,weak)id<WKScriptMessageHandler> scriptDelegate;

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;

@end

.m 文件

#import "WeakScriptMessageDelegate.h"

@implementation WeakScriptMessageDelegate
- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate
{
    self = [super init];
    if (self) {
        _scriptDelegate = scriptDelegate;
    }
    return self;
}

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    
    [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}
@end

使用

1、导入该类

// addScriptMessageHandler 使用新类

[_webView.configuration.userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"xxxx"];

2、依旧removeAllUserScripts

- (void)dealloc{
    [self.webView.configuration.userContentController removeAllUserScripts];
}

相关文章

网友评论

    本文标题:iOS WKWebView与JS交互

    本文链接:https://www.haomeiwen.com/subject/jwxlgxtx.html