OC与JS数据交互

  • iOS7之后有了JavaScriptCore框架使得OC与JS的交互变得简单了起来.
  • 在学习webView的时候,发现OC与JS做交互时用的是截取webView的响应来获得想要的数据(不得不佩服,办法很高端)。感觉这种办法太蛋疼了,于是抱着试一试的心态到官方文档搜索JavaScript关键字,于是出来了下面一段
QQ20160518-0.png
  • 看到了这句话很是兴奋啊!于是又往下继续找
QQ20160518-1.png
  • 竟然还有例子耶,来试试吧!

    • 结果可想而知,并没有什么卵用webView根本没有windowScriptObject方法
    • 回头一看还有一句 any WebKit-based OS X application原来是OS X才能用
  • 然后继续上网找资料啊

    • 找到了这样一个博客
      http://blog.csdn.net/lwjok2007/article/details/47058101/
      讲了在OC执行JS
      http://blog.csdn.net/lwjok2007/article/details/47058795
      讲了在JS调用OC方法
      里面写了怎样使用JavaScriptCore框架让OC和JS的交互,我就不搬运了。里面的关于导入框架,介绍JavaScriptCore的使用等等一些东西写的都比较清楚了。
      然后我把里面的东西拿出来验证了一下,也把JSExport用法写的更详细了一点,block的方式没有使用。上面的文章里面没有讲到 JSExportAs宏,所以JS函数名称比较恶心
  • JS与OC的数据类型对应如下<JSValue.h>有描述

QQ20160518-2.png
  • 要说的都在注释里了,OC代码如下(HTML在最下面):

#import "ViewController.h"
#import <JavaScriptCore/JavaScriptCore.h>

//自己定义一个协议遵守JSExport协议,然后想要导出这些方法的类再遵守这个协议就可以了
@protocol ObjcExportMethod <JSExport>

//JSExportAs宏将 "- showNumber1:andNumber2:"方法名 转换为showNumber(param1, param2)
//如果不使用JSExportAs转换,那么在js中调用的函数名为showNumber1AndNumber2(param1, param2);
//注意:JSExportAs宏只适合转换有参的方法,不能转换无参的方法
JSExportAs(showNumber,
- (void)showNumber1:(NSNumber *)n1 andNumber2:(NSNumber *)n2
);

JSExportAs(returnSum,
- (NSNumber *)returnSumWithNum1:(NSNumber *)n1 andNum2:(NSNumber *)n2
);

JSExportAs(dictTest,
- (void)dictTest:(NSDictionary *)dict
);

JSExportAs(arrayTest,
- (void)arrayTest:(NSArray *)array
);

- (void)show;
- (NSString *)returnString;
- (NSDictionary *)returnDict;
- (NSArray *)returnArray;
@end

/**
  * UIViewController
  */
@interface ViewController () <UIWebViewDelegate, ObjcExportMethod>
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@end


@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //加载本地测试网页
    [self.webView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"]]];

}

#pragma mark - <ObjcExportMethod>

/**
 *  无参导出方法
 */
- (void)show
{
    NSLog(@"%s", __func__);
}
/**
 *  返回一个OC字符串到JavaScript
 */
- (NSString *)returnString
{
    return @"从OC返回成功";
}
/**
 *  返回一个OC数组到JavaScript
 */
- (NSArray *)returnArray
{
    return @[@(1), @"hello"];
}
/**
 *  返回一个OC字典到JavaScript
 */
- (NSDictionary *)returnDict
{
    return @{
             @"name" : @"jack",
             @"date" : @[@(1), @"hello"]
             };
}
/**
 *  从JavaScript接收两个NSNumber参数,计算他们的和并返回计算结果到JS
 */
- (NSNumber *)returnSumWithNum1:(NSNumber *)n1 andNum2:(NSNumber *)n2
{
    return @(n1.intValue + n2.intValue);
}
/**
 *  从JavaScript接收两个NSNumber类型的值,打印出来
 */
- (void)showNumber1:(NSNumber *)n1 andNumber2:(NSNumber *)n2
{
    NSLog(@"number1 = %@, number2 = %@", n1, n2);
}
/**
 *  从JavaScript接收一个字典
 */
- (void)dictTest:(NSDictionary *)dict
{
    NSLog(@"%@",dict);
}
/**
 *  从JavaScript接收一个数组
 */
- (void)arrayTest:(NSArray *)array
{
    NSLog(@"%@", array);
}


#pragma mark - <UIWebViewDelegate>

/**
 *  完成加载
 */
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    //得到当前页面的JSContext,如果不在这里获得当前网页的context可能有问题
    JSContext *js = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    //设置 js 代码中的method对象为控制器
    js[@"method"] = self;
    
    //在OC中执行js并取得js返回的数据
    //方式1 使用JSContext的对象方法执行JS脚本
    NSString *jsScript = @"document.title";     //获取网页标题
    //evaluateScript方法返回的是JSValue类型的对象,需要将类型转换为OC对象
    NSString *title = [js evaluateScript:jsScript].toString;
    self.navigationItem.title = title;
    NSLog(@"evaluateScript --->  %@",title);

    //方式2 使用webView的对象方法执行js,该方法返回的数据类型始终是NSString,不管JS实际传递过来的是什么类型,
    //如JS传递过来的是10 那么该方法的返回值任然是字符串
    title = [webView stringByEvaluatingJavaScriptFromString:jsScript];
    NSLog(@"stringByEvaluating ---> %@", title);
}

@end

  • 测试用HTML代码如下:
<html>
    <head>
    <meta charset="UTF-8"/>
    <title>测试网页</title>
    <script>
        //遍历数组
        function ArrayFun(array)
        {
            for(var i = 0; i < array.length; i++)
            {
                alert(array[i]);
            }
        }
        // 遍历字典
        function DictionaryFun(dict)
        {
            for (var key in dict)
            {
                alert(key + " : " + dict[key]);
            }
        }
    </script>
    </head>
    

    <body>
        <h5 style="color:blue" onclick="method.show();">调用OC无参无返回值方法</h5>
        <h5 style="color:blue" onclick="alert(method.returnString());">从OC返回字符串</h5>
        <h5 style="color:blue" onclick="method.showNumber(1,2);">传递2个整数到OC</h5>
        <h5 style="color:blue" onclick="alert(method.returnSum(10,20));">传递2个整数到OC,得到他们的和</h5>
        <h5 style="color:blue" onclick="method.arrayTest([1,2,'hello oc', {'name':'jack'}]);">传递数组到OC</h5>
        <h5 style="color:blue" onclick="method.dictTest({'name':'jack', 'data':[1, 'hello', {'age' : 10}]});">传递字典到OC</h5>
        <h5 style="color:blue" onclick="DictionaryFun(method.returnDict());">从OC返回字典</h5>
        <h5 style="color:blue" onclick="ArrayFun(method.returnArray());">从OC返回数组</h5>
    </body>
    
</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 找到了这样一个博客 http://blog.csdn.net/lwjok2007/article/details/...
    闲云清烟阅读 220评论 0 0
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,045评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,943评论 4 60
  • 图文 | 白桦czh 阿黄被送来的时候,是在一个冬天,正值我生命中最灰暗的一段时光。当然那时候它还不叫阿黄,它只是...
    白桦czh阅读 2,686评论 97 114
  • 我家的网络有点问题,邻居大哥带着4岁的儿子和他同事晚上来看了一下。哥哥刚进来就看到一包小花片,马上拿着就拆了,孩子...
    小小小文盲阅读 111评论 0 0