Object-C部分##
1、导入框架和对应的头文件
JavaScriptCore.framework // 框架
#import <JavaScriptCore/JavaScriptCore.h> //头文件
2、创建类文件,继承NSObject
3、编写类JSAndOCMutually.h
代码
创建协议JSAndOCMutuallyProtocol
,协议遵循<JSExport>
创建的类遵循创建的
代码示例如下:
#import <JavaScriptCore/JavaScriptCore.h>
@protocol JSAndOCMutuallyProtocol <JSExport>
// JavaScript中调用Object-C的方法都写在此处,否则JS将找不到对应的方法
// 无参数
-(void)FunctionNoParameter;
// 一个参数
-(void)FunctionOneParameter:(NSString *)message;
// 两个参数
-(void)FunctionTwoParametersWithFirstParameter:(NSString *)message1 SecondParameter:(NSString *)message2;
@end
@interface JSAndOCMutually : NSObject <JSAndOCMutuallyProtocol>
@end
4、实现类JSAndOCMutually.h
遵循协议中对应的方法
代码示例如下:
@implementation JSAndOCMutually
-(void)FunctionNoParameter{
NSLog(@"this is iOS FunctionNoParameter");
}
-(void)FunctionOneParameter:(NSString *)message{
NSLog(@"this is iOS FunctionOneParameter,FirstParameter=%@",message);
}
-(void)FunctionTwoParametersWithFirstParameter:(NSString *)message1 SecondParameter:(NSString *)message2{
NSLog(@"this is iOS FunctionTwoParametersWithFirstParameter,FirstParameter=%@ SecondParameter=%@",message1,message2);
}
@end
5、WebView的代理中需要编写的代码
5.1、在遵循<UIWebViewDelegate>
的ViewController中导入创建的类头文件以及库头文件
#import <JavaScriptCore/JavaScriptCore.h>
#import "JSAndOCMutually.h"
5.2、在UIWebViewDelegate
代理的结束加载方法中,编写以下代码,
- (void)webViewDidFinishLoad:(UIWebView *)webView{
JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
JSAndOCMutually *jsandOC = [JSAndOCMutually new];
context[@"test"] = jsandOC; // test 就是即将注入JavaScript中的对象
// block 方式
// context[@"test"] = ^() {
// block代码块,个人认为不赞成使用此种方式。
// };
// 模拟JS调用OC的方法
// NSString *jsStr1=@"test.TestNOParameter()";
// [context evaluateScript:jsStr1];
}
至此,Object-C部分的代码基本结束,接下来就是在JavaScript中通过注入的“test”对象进行方法的调用。
JavaScript部分##
在WebView加载的HTML文件中JS代码部分
var message1 = "MeaasgeOne";
var message2 = "MeaasgeTwo";
// 无参数方法的调用
window.test.FunctionNoParameter();
// 一个参数方法的调用
window.test.FunctionOneParameter(message1);
// 两个参数方法的调用
window.test.FunctionTwoParametersWithFirstParameterSecondParameter(message1,message2);
// 如果有返回值,只需要声明一个变量接收返回值即可。
至此,简单的JS与OC的交互就结束了。
下面将是重点、重点、重点。#
现在,为了进行热更新,许多的APP开始使用iOS的壳加H5的内容,在我们的项目中H5请求后台数据时,需要通过JS与OC的交互获取原生态代码中的一些参数。
这时就出现了一个重要的问题。
问题描述:页面A与页面B,两个页面均需要进行网络请求,网络请求传给后台的参数均需要原生态的一些参数,当用WebView加载页面A时数据可以完美的呈现,点击跳转按钮,跳转到页面B,发现数据没有出现,然后返回页面A,发现页面A后台获取的数据也没有了。
由于页面A没有做数据缓存,因此每次的页面数据都必须通过网络请求到后台获取。这还不是最重要的。
经过测试发现,数据获取不到的最重要的原因:跳转页面B以及返回页面A都需要JS与OC进行交互,JS调用OC的方法获取原生态参数,而由于调转不是由原生态进行控制,只有第一次加载页面时,对象test注入到JS中,调用原生态方法成功;而后续的页面跳转以及网络请求均发生在对象test注入到JS加载之前,导致JS代码已经加载完成,而对象test还没有注入,因此调用原生态方法的失败。
解决方法:在JS代码中,将获取原生态参数的方法以及网络请求方法放到延迟方法中。
代码示例如下:
setTimeout(function () {
window.test.TestTowParameterSecondParameter(message1,message2);
}, 100);
// 经过测试100毫秒的延迟,就可以达到效果,足够对象iOS注入到JS中。