iOS与js交互

1.UIWebview的js交互

iOS7之后苹果推出了JavaScriptCore这个框架,从而让web页面和本地原生应用交互起来非常方便,而且使用此框架可以做到Android那边和iOS相对统一,web前端写一套代码就可以适配客户端的两个平台,从而减少了web前端的工作量。

JavaScriptCore有如下几个类
#import "JSContext.h"
#import "JSValue.h"
#import "JSManagedValue.h"
#import "JSVirtualMachine.h"
#import "JSExport.h"
1>JSContext代表一个JavaScript的执行环境的一个实例。

创建方法

JSContext *context = [self.myWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
2>JSValue的主要作用就是用来接收JSContext执行后的返回结果
<script type="text/javascript">
      var myObject = "myObject";
  </script>
JSValue *myObject = self.context[@"myObject"]; 
NSLog(@"%@",[myObject toString]);
3>JSManagedValue JS和OC对象的内存管理辅助对象。由于JS内存管理是垃圾回收,并且JS中的对象都是强引用,而OC是引用计数。如果双方相互引用,势必会造成循环引用,而导致内存泄露。我们可以用JSManagedValue保存JSValue来避免。
4>JSVirtualMachine JS运行的虚拟机,有独立的堆空间和垃圾回收机制。
5>JSExport 一个协议,如果JS对象想直接调用OC对象里面的方法和属性,那么这个OC对象只要实现这个JSExport协议就可以了。

iOS调用js方法

#pragma mark  js代码
// 有参数
function numAddMethod(num1,num2){
    alert(num1 + num2);
    return num1 + num2;
}
// 无参数
function numAddMethod2(){
    alert('调用numAddMethod2');
}
#pragma mark  iOS方法
- (void)iOSMethod{
     //创建上下文
    JSContext *context = [self.myWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    //调用有参数的js方法
    JSValue *value = [context[@"numAddMethod"] callWithArguments:@[@(5),@(6)]];
    //调用无参数的js方法
    JSValue *value2 = [context[@"numAddMethod2"] callWithArguments:@[]];

    NSLog(@"有参数返回值=%d === 无参数返回值",value.toInt32,value2.toInt32);
     //打印结果,有参数返回值=11===无参数返回值0
}

js调用iOS方法

#pragma mark  js代码
<head>
    <script type = "text/javascript">
         function viewClicked(){
             share('1','2','3');
         }
     </script>
</head>
<body>
     <button type="button" onclick="viewClicked()">Click Me!</button>
</body>
#pragma mark  iOS代码
-(void)viewDidLoad{
    [super viewDidLoad];
    JSContext *context = [self.myWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    context[@"share"] = ^(){
        NSArray *args = [JSContext currentArguments];
        for (JSValue *jsValue in args) {
            NSLog(@"%@",jsValue.toString);
        }
    };
    //arguments保存js传入的参数,打印结果为1,2,3.
}

WKWebView的js交互

首先来一段代码,来创建一个WKWebView


@interface WKWebViewController ()<WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler>
    
@property (nonatomic, strong) WKWebView *webView;

@property (nonatomic, strong) WKUserContentController *userContent;

@end

@implementation WKWebViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    self.userContent = [[WKUserContentController alloc] init];
   
    [self.userContent addScriptMessageHandler:self name:@"ocMethod"];
    
    config.userContentController = self.userContent;
    self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
    
    self.webView.UIDelegate = self;
    self.webView.navigationDelegate = self;
    [self.view addSubview:self.webView];
    
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [self.webView loadRequest:request];
}
    

特别关注WKUserContentController的addScriptMessageHandler:name:方法


/*! @abstract Adds a script message handler.
  //添加一个js要调用的方法
 @param scriptMessageHandler The message handler to add.
 //添加消息处理界面
 @param name The name of the message handler.
 //js要执行的方法名称
 @discussion Adding a scriptMessageHandler adds a function
 window.webkit.messageHandlers.<name>.postMessage(<messageBody>) for all
 frames.
  //需要js执行的方法规则
  //window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
 */
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;

这个方法可能会引起内存泄漏,解决方法百度上有很多,这里不做说明。

1>iOS原生方法调用js方法
#pragram mark -- js代码
function jsMethod(obj){
    return obj;
}

#pragram mark -- iOS代码
- (void)iOSMethod{
    NSDictionary *dict = @{@"key1":@"value1",@"key2":@"value2"};
    NSData *dictData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
    NSString *dictStr = [[NSString alloc] initWithData:dictData encoding:NSUTF8StringEncoding];
    NSString *jsStr = [NSString stringWithFormat:@"jsMethod(%@)",dictStr];
    [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        NSLog(@"return == %@",result);
    }];
    //iOS给js传入多个参数可以通过转成字符串的方法传给js
    //打印结果为@{@"key1":@"value1",@"key2":@"value2"},说明js方法返回值都在result里面
}
    
2>js调用iOS原生方法
#pragram mark -- js代码
<head>
    <script type = "text/javascript">
         function viewClicked(){
             //固定写法,方法名为iOS原生要执行的方法(这里的方法名为ocMethod,上面已经注册过),参数放在()中
             window.webkit.messageHandlers.ocMethod.postMessage({'key':'value'});
         }
     </script>
</head>
<body>
     <button type="button" onclick="viewClicked()">Click Me!</button>
</body>

#pragram mark -- iOS代码
#pragram mark -- WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    NSString *messageName = message.name;
    if ([@"ocMethod" isEqualToString:messageName]) {
        id messageBody = message.body;
        NSLog(@"%@",messageBody);
        //当js调用ocMethod时,就可以来到这里,然后就可以在这里写iOS原生代码了,js所传的参数都在message.body里面了
    }
}

UIWebView和WKWebView与js交互的方法不能通用,项目在换webView时,会造成一点的麻烦。

使用WebViewJavascriptBridge可以适配两种webView

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容