iOS开发-进阶:JS与OC的交互

在移动应用的项目中, web 相比原生应用有如下优点:

  • 版本可以随时更新, 效率高;
  • 可动态配置要展示的数据, 及数据来源.
  • 原生应用中, 如果一个页面的展示, 需要多次调用不同的网络请求, 并且, 上一次请求的结果是下一次请求的参数, 这样按顺序调用网络并且等待网络返回的数据会消耗大量的时间严重降低应用性能, 影响用户体验.
  • 同样, 如果在处理事件时调用网络请求过多, 并且返回值均是弱逻辑. 使代码结构复杂. 程序出口过度, 给代码的测试, 可读性和修改带来很大的困难.

面对上面的情况 (尤其是3,4条) 时, 使用 web 可以更容易的满足项目需求, 实现难度较低, 同时可以动态配置, 一个通用功能的网页, 可以满足大部分类似的需求. 但是 web 的劣势也很多, 如用户体验, 性能, 数据存储, 手机硬件的调用等. 在 App 内使用 web 时, sometimes 会有点击网页跳转界面的需求. 而使  web 调用 Objective-C 的方法目前只知道 Javascript. 如有其它方式, 请告诉我~ 

这里介绍二种方法实现 JS 与 OC 的交互. 

一. WebViewJavascriptBridge 是 github 上开源的第三方库, 利用 bridge 对象实现 JS 与 OC 的交互. 用 block 传递参数并续写操作. 这种方法优点是在 OC 端代码已经封装好, API 简单易用; 缺点 web 端的代码实现与 Android 不兼容, 因此放弃使用. 

github 地址: https://github.com/marcuswestin/WebViewJavascriptBridge

使用的方法在Demo中有详细的说明.


二. JavaScriptCore.framework 实现了 JS 与 OC 的交互, 这个库是在 iOS7 时推出的.

下面在一个例子中讲下如何实现 JS 与 OC 互调;

1. 导入 JavaScriptCore.framework; 

在项目 TARGETS 中 GENERAL 下的 Linked Frameworks and Libraries 中添加 JavaScriptCore.framework;


2. 现在假设 web 端 JS 有如下代码:

//JS 调 OC
function WebToApp(sDataKey, iAction) {
    var sJsonStr = '{"sDataKey":"' + sDataKey + '","iAction":"' + iAction + '"}';
    //$("#" + sDataKey).val("");
    WebAppObj.WebToApp(sJsonStr);
}
//OC 回调 JS
function AppToWeb(sJsonStr)
{
    //alert(sJsonStr)
    var obj = (new Function("", "return " + sJsonStr))();
    $("#" + obj.sDataKey).val(obj.sData);
}
3. 在 OC 中创建一个类, 测试用的 WebAppObj 类

WebAppObj.h

#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>  
@class WebAppObj;

//首先创建一个实现了JSExport协议的协议
@protocol WebAppObjProtocol <JSExport>

//此处我们测试几种参数的情况
- (void)WebToApp:(NSString*)JsonStr;
@end

@protocol WebAppObjDelegate <NSObject>
- (void)didReceiveJSData:(NSString *)JsonStr;
@end

@interface WebAppObj : NSObject <WebAppObjProtocol>
@property(nonatomic, strong) id<WebAppObjDelegate> delegate;
@end
WebAppObj.m

@implementation WebAppObj

- (void)WebToApp:(NSString *)JsonStr
{
    if ([self.delegate respondsToSelector:@selector(didReceiveJSData:)]) {
         [self.delegate didReceiveJSData:JsonStr];
    }
}
@end


4. JS 调 OC: 在webview的代理方法: - (void)webViewDidFinishLoad:(UIWebView *) 中注入 JSContext, 并将之前的 WebAppObj 对象传递到 context 中;

然后实现 WebAppObj 的代理方法; 当网页的操作触发了 Function WebToApp 方法时, OC 端通过 WebAppObj 的代理方法被 JS 调用, 并将 JsonStr 从 web 传递给 OC;

- (void)webViewDidFinishLoad:(UIWebView *)webView{
    JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    WebAppObj *webObj = [WebAppObj new];
    webObj.delegate = self;
    context[@"WebAppObj"] = webObj;
}

- (void)didReceiveJSData:(NSString *)JsonStr
{
#warning mark - JS调OC要在主线程执行UI否则报错!
    __unsafe_unretained __typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"%@",JsonStr);
    });
}

5. OC 调 JS: 下面的代码演示了 OC 调用 JS 的方式;

    __unsafe_unretained __typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        //1.模型转JSON
        NSString *jsonStr = [yourModel toJSONString];
        //2.OC调JS
        JSContext *context=[weakSelf.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        NSString *javaScriptStr =[NSString stringWithFormat:@"AppToWeb('%@')", jsonStr]; //准备执行的js代码
        [context evaluateScript:javaScriptStr];//通过oc方法调用js
    });


 














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值