ios url编码_IOS和JS的交互,看这一篇文章就够了

IOS和JS的交互,看这一篇文章就够了

创作不易,请珍惜,之后会持续更新,不断完善
Demo地址

目录

  • WKWebView使用、JS的交互

WKWebView使用、JS的交互

演示(本来想贴张GIF作为演示流程的,害,太模糊不清了还是算了,话说简书写起来不方便呀,图片大小清晰度也挺难看的,吐槽下),顺便列举下控制台的所有输出作为例证,相关输出用到的地方在代码注释处有写

a85459c908fc33033a6065faf0e740f5.png

控制台输出

创建WKWebView

    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    // 创建wkWebView
    self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
    self.wkWebView.UIDelegate  = self;
    self.wkWebView.navigationDelegate = self;
    [self.view addSubview:self.wkWebView];

WKNavigationDelegate

页面加载完成之后调用, 定义一个全局变量 arr

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
    // 导航栏标题
    self.title = webView.title;
    // 定义一个全局变量 arr
    NSString *jsStr = @"var arr = [5, '谢佳培', 'xiejiapei']; ";
    [self.wkWebView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        // 页面加载完成之后调用, 定义一个全局变量 arr: (null)----(null)
        NSLog(@"页面加载完成之后调用, 定义一个全局变量 arr: %@----%@",result, error);
    }];
}

拦截网页的跳转链接: 在发送请求之前,决定是否跳转,点击提交按钮的时候会调用该方法

e54d9d4088b8597f75ea0a750a5cb635.png

提交.png

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    // URL = @"lgedu://jsCallOC?username=Cooci&password=123456"
    // 获取请求的URL
    NSURL *URL = navigationAction.request.URL;
    // 获取URL Scheme,其作用为方便app之间互相调用而设计的
    NSString *scheme = [URL scheme];

    // 拦截lgedu
    if ([scheme isEqualToString:@"lgedu"])
    {
        // url是地址, 在某个主机目录下的文件的唯一标识符(统一资源定位符url)
        // domain是域名, 比如baidu.com就是域名,而其对应的ip地址指向了百度的服务器
        // host是主机, 默认情况http协议是80端口 https协议是443端口
        NSString *host = [URL host];

        // 主机名为jsCallOC
        if ([host isEqualToString:@"jsCallOC"])
        {
            // 解析URL
            NSMutableDictionary *temDict = [self decoderUrl:URL];
            NSString *username = [temDict objectForKey:@"username"];
            NSString *password = [temDict objectForKey:@"password"];
            // 用户名和密码:谢佳培------123456
            NSLog(@"用户名和密码:%@------%@",username,password);
        }
        else
        {
            NSLog(@"不明地址 %@",host);
        }
        // 不允许跳转
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    // 允许跳转
    decisionHandler(WKNavigationActionPolicyAllow);
}

解析URL地址,取得JS中的值

// 解析URL地址
- (NSMutableDictionary *)decoderUrl:(NSURL *)URL
{
    // URL = @"lgedu://jsCallOC?username=谢佳培&password=123456"
    // 分开参数
    NSArray *params = [URL.query componentsSeparatedByString:@"&"];
    NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];

    for (NSString *param in params)
    {
        // 分开键值对
        NSArray *dictArray = [param componentsSeparatedByString:@"="];

        if (dictArray.count 1)
        {
            /** 网络请求拼接中文参数,用户名登陆等很多地方会用到中文,UTF8编码显得颇为重要
             *  编码:
             *  NSString* hStr =@"你好啊";
             *  NSString* hString = [hStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
             *  NSLog(@"hString === %@",hString); // hString === %E4%BD%A0%E5%A5%BD%E5%95%8A
             *
             *  解码:
             *  NSString*str3 =@"\u5982\u4f55\u8054\u7cfb\u5ba2\u670d\u4eba\u5458\uff1f";
             *  NSString*str5 = [str3 stringByRemovingPercentEncoding];
             *  NSLog(@"str5 ==== %@",str5);// str5 ====如何联系客服人员?
             */
            // 取值, 中文解码
            NSString *decodeValue = [dictArray[1] stringByRemovingPercentEncoding];
            // 解码后放入tempDic
            [tempDic setObject:decodeValue forKey:dictArray[0]];
        }
    }

    return tempDic;
}

JS中相关代码如下

        >input type="button" value="提交" onclick="submit()" /br /<
        function submit(){
            alert('点击了提交按钮,调用loadURL方法获得URL');
            loadURL("lgedu://jsCallOC?username=谢佳培&password=123456");
        }

        function loadURL(url) {
            var iFrame;
            iFrame = document.createElement("iframe");
            iFrame.setAttribute("src", url);
            iFrame.setAttribute("style", "display:none;");
            iFrame.setAttribute("height", "0px");
            iFrame.setAttribute("width", "0px");
            iFrame.setAttribute("frameborder", "0");
            document.body.appendChild(iFrame);
            iFrame.parentNode.removeChild(iFrame);
            iFrame = null;
        }

WKUIDelegate

使用OC样式的弹出警告框,覆盖JS的丑陋样式

// 警告框
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
    // 使用OC样式的弹出警告框,覆盖JS的丑陋样式
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *knowAction = [UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        // 回调完成
        completionHandler();
    }];
    [alert addAction:knowAction];
    [self presentViewController:alert animated:YES completion:nil];
}

OC 调用 JS方法

通过  evaluateJavaScript调用了JS中的showAlert方法
演示图:

35fe12367e1ad2081be93c3f3b6fc116.png

代码片段:OC

    // JS方法
    // alert('我是一个可爱的弹框 \n'+messgae+'\n'+arr[1]);
    // arr[1]来自在我们在页面加载完成后定义的全局变量arr
    // msg: 我是一个可爱的弹框 登陆成功 谢佳培
    NSString *jsStr = [NSString stringWithFormat:@"showAlert('%@')",@"嗨,这是通过OC调用showAlert方法哦"];

    // OC 调用 JS方法
    [self.wkWebView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        // OC 调用 JS方法: token----(null)
        // Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,
        // 当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
        // 使用Token的目的:Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。
        NSLog(@"OC 调用 JS方法: %@----%@",result, error);
    }];

代码片段:JS

        function showAlert(messgae){
            alert('我是一个可爱的弹框 \n'+messgae+'\n'+arr[1]);
            return "token";
        }

WKUserContentController

调整按钮大小适应APP页面

configuration.userContentController = [self wkwebViewScalPreferences];

6a90029df2278c7e6f99b427d18f2359.png

// 调整按钮大小适应APP页面
- (WKUserContentController *)wkwebViewScalPreferences
{
    // js注入: json调整按钮大小脚本
    NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";

    /** WKUserScript就是帮助我们完成JS注入的类,它能帮助我们在页面填充前或js填充完成后调用
     * 参数1:脚本的源代码
     * 参数2:脚本应注入网页的时间,是个枚举,End表示:在文档完成加载之后,但在其他子资源完成加载之前插入脚本
     * 参数3:是否加入所有框架,还是只加入主框架
     */
    WKUserScript *wkUserScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
    WKUserContentController *wkUserContentController = [[WKUserContentController alloc] init];
    [wkUserContentController addUserScript:wkUserScript];

    return wkUserContentController;
}

MessgaeHandle

JS相关代码: 发送了消息

        >input type="button" value="messgaeHandle" onclick="messgaeHandle()" /<>br /<
        function messgaeHandle(){
            // js -- android
            alert('给messageHandlers页面发送了“青春气息”');
            window.webkit.messageHandlers.messgaeOC.postMessage("青春气息");
        }

viewWillAppear中监听消息,但是注意在viewWillDisappear需要移除,否则会造成循环引用,不会调用到dealloc方法

// 循环引用:self - webView - configuration - userContentController - self
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    // 添加scriptMessageHandler到所有的frames中,
    // html5中需要添加window.webkit.messageHandlers.>name<.postmessage>messageBody
    [self.wkWebView.configuration.userContentController addScriptMessageHandler:self name:@"messgaeOC"];
}// 需要根据name移除所注入的scriptMessageHandler来打破循环引用, 否则不会调用到dealloc方法
- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [self.wkWebView.configuration.userContentController removeScriptMessageHandlerForName:@"messgaeOC"];
}
- (void)dealloc
{NSLog(@"dealloc:溜了溜了");
}

WKScriptMessageHandler

WKWebView收到ScriptMessage时回调此方法

4e63ad38f6b9766fa4ad82b479589da4.png

// WKWebView收到ScriptMessage时回调此方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    if (message.name)
    {
        // OC 层面的消息
    }
    // message == messgaeOC --- 青春气息
    NSLog(@"消息是:%@ --- %@",message.name,message.body);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值