小工具      在线工具  汉语词典  css  js  c++  java

如何使用JavascriptCore与UIWebView交互拦截Html5

IOS 额外说明

收录于:42天前

转载自:http://www.07net01.com/2016/12/1734731.html

本篇文章的示例代码可以在 我的Github 上进行下载。

在上一篇文章中我们讨论了 爪哇ScriptCore 的基本使用,如何在脱离 UIWebView 的情况下让 javascript 与原生进行交互。

但是,在混合开发过程中,我们需要的是让原生应用能与 UIWebView 进行流畅的交互。就如上一篇文章讲到的,从 iOS 2 以来,我们与 UIWebView 进行交互的唯一方式就是使用 stringByEvaluatingJavaScriptFromString: 方法拦截请求,像在 Github 上很火的 WebViewJavascriptBridge 就是使用这一原理来实现的。不幸的是,这一现状在 iOS 7 以后并没有改变,虽然苹果公司。在 iOS 7 之后推出了 JavaScriptCore 这个新工具,但是官方并没有提供获取 UIWebView 的 JSContext 方法。

使用 JavaScriptCore 与 UIWebView 结合进行混合开发,这个需求是如此地合理,以致于我相信不会只有我一个人有这种想法。果然,互联网上牛人多,直接使用 谷歌 一搜,果然让我找到别人提供的两种解决方案

注意:本篇文章所描述的方法并非是苹果官方提供的——可能甚至是他们所不赞成的,这些方法在文章写作的时候还是可以使用的,但是不保证之后会一直好用,请留意。

问题描述

当我们需要使用 JavaScript 与原生交互时,我们需要一个 JSContext 实例。当我们使用 JavaScript 代码开发自己的功能时,我们可以手动创建 JSContext。

每个 UIWebView 实例都有自己的 JSContext 对象。当我们想要与UIWebView交互时,第一步就是获取它们的JSContext对象。不过苹果官方并没有提供UIWebView中获取JSContext对象的方法。

经过查找,发现常用的方法有两种:

  1. 使用KVC
  2. 使用类别

本文将通过一个例子来演示。代码中只使用了第二种方法,因为我个人认为更方便。

使用KVC

使用这种方法非常简单,一句话代码就能描述清楚:

JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

只要我们能够获取到UIWebView的实例,我们就可以直接使用KVC的方法来获取它的JSContext对象,就这么简单。

使用类别

第二种方法就是为 NSObject 添加一个分类,并使用这个分类来实现 WebKit 的didCreateJavaScriptContext 回调,这种方法的具体描述可以参考 https://github.com/TomSwift/UIWebView-TS_JavaScriptContext 。

具体实现代码如下:

@implementation NSObject(JSContextTracker)

+ (NSMapTable *)JSContextTrackerMap {
    static NSMapTable *contextTracker;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        contextTracker = [NSMapTable strongToWeakObjectsMapTable];
    });
    return contextTracker;
}

- (void)webView:(id)unused didCreateJavaScriptContext:(JSContext *)ctx forFrame:(id)alsoUnused {
    NSAssert([ctx isKindOfClass:[JSContext class]], @"bad context");
    if (!ctx)
        return;
    NSMapTable *map = [NSObject JSContextTrackerMap];
    static long contexts = 0;
    NSString *contextKey = [NSString stringWithFormat:@"jsctx_%@", @(contexts++)];
    [map setObject:ctx forKey:contextKey];
    ctx[@"JSContextTrackerMapKey"] = contextKey; // store the key to the map in the context itself
}

+ (JSContext *)contextForWebView:(UIWebView *)webView {
    // this will trigger didCreateJavaScriptContext if it hasn't already been called
    NSString *contextKey = [webView stringByEvaluatingJavaScriptFromString:@"JSContextTrackerMapKey"];
    JSContext *ctx = [[NSObject JSContextTrackerMap] objectForKey:contextKey];
    return ctx;
}
@end

项目中增加这个分类之后,以后要获取 UIWebView 的 JSContext 对象,只需要使用[NSObject contextForWebView:myWebView] 就可以了。

例子

示例代码是一个联系人列表。项目中有一个html文件,里面显示了一个添加用户的表单。单击提交后,新联系人将添加到本地数组中并显示在 UITableView 中。

同时,代码中还演示了上一篇文章中讨论的使用JavaScript代码调用native的方法。

核心代码在 XGAddContactWebViewController 文件中,这个控制器里面有一个 UIWebView 实例,在viewDidLoad 方法中获取了 JSContext 对象:

self.jsContext = [NSObject contextForWebView:self.webView];

然后,在 - (void)webViewDidFinishLoad:(UIWebView *)webView 回调中,使用这个 JSContext 来调用原生的方法:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    [self.loadingView stopAnimating];
    
    [self.jsContext setExceptionHandler:^(JSContext *context, JSValue *value) {
        NSLog(@"WEB JS: %@", value);
    }];
    
    self.jsContext[@"myStore"] = self.store;
    self.jsContext[@"XGContact"] = [XGContact class];
    
    NSString *jsPath = [[NSBundle mainBundle] pathForResource:@"add_a_contact" ofType:@"js"];
    NSString *jsCode = [NSString stringWithContentsOfFile:jsPath encoding:NSUTF8StringEncoding error:nil];
    [self.jsContext evaluateScript:jsCode];
}

完整的示例代码请参考我的Github。



. . .

相关推荐

额外说明

Eclipse中设置jvm参数的三种方法

方式1. 修改Elipse运行JRE默认JVM参数 打开Eclipse,选择Window--Preferences...在对话框左边的树上双击Java,再双击Installed JREs,在右边选择前面有对勾的JRE,再单击右边的“Edit”按钮,出现一

额外说明

MYSQL01 Advanced_Linux版本安装、各级字符集、字符集及比较规则、SQL大小写规范

文章目录 ①. MySQL - linux版安装 ②. 字符集的相关操作 ③. 各级别的字符集 ④. 字符集与比较规则(了解) ⑤. SQL大小写规范 ⑥. sql_mode的合理设置 ①. MySQL - linux版安装 ①. 进入mysql官网,找

额外说明

推荐系统[八]算法实践总结V3:重排在快手短视频推荐系统中的应用and手淘信息流多兴趣多目标重排技术

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、

额外说明

k8s数据存储之Volume使用详解

目录 一、什么是Volume 二、k8s中的Volume 三、k8s中常见的Volume类型 四、Volume 之 EmptyDir  4.1 EmptyDir 特点

额外说明

博客内容索引(2021-1-10)

源码系列 Spring初始化 学会看源码 Java注解机制 Angular win10搭建Angular环境并运行hello-world 使用IDEA开发Angular 组件的基本操作 K8S 概述 Docker Docker的安装与初始化配置 dock

额外说明

计算性能的提升之混合式编程(MXNet)

        平时的练习与调试基本都是使用命令式编程,但是计算性能比较差,而使用符号式编程可以提高性能,在 MXNet中的命令式编程和符号式编程的优缺点,这篇文章也有介绍这两者的一些基本区别和操作。 一般来说我们是在开发的时候使用命令式编程,经过调试测

额外说明

[Web Chart系列之五] 3. 实战draw2d 之图形填充色(纯色 or 渐变)

颜色渐变 draw2d 目前没有提供直接对Figure 设置渐变效果的API. 但是raphael 有提供, 这样的话基本上在draw2d实现渐变成为可能。 颜色渐变功能来源 raphael 提供的图形背景色渐变的设置:看例子 <!--Add by os

额外说明

RandomAccessFile类使用详解

RandomAccessFile类使用详解 1.RandomAccessFile特点 RandomAccessFile是java Io体系中功能最丰富的文件内容访问类。即可以读取文件内容,也可以向文件中写入内容。但是和其他输入/输入流不同的是,程序可以直

额外说明

(小白必看)详解yolov5训练自己的数据集 & 使用香烟数据集训练yolov5识别香烟

1.数据集资源 https://download.csdn.net/download/qq_42864343/88110620?spm=1001.2014.3001.5503 https://download.csdn.net/download/qq_4

额外说明

WordPress 4.5的新功能

名为“Coleman”的 WordPress 4.5 于几分钟前发布。它是 2016 年第一个主要 WordPress 版本,并带来了一些令人兴奋的新功能。在本文中,我们将向您展示 WordPress 4.5 中的新增功能,以及更新网站后应尝试哪些功能。

ads via 小工具