最近項目里面有有個商品活動界面茴厉,要與web端傳值凌净,將用戶在網(wǎng)頁點擊的商品id 傳給客戶端搁骑,也就是js交互斧吐,其實再說明白一點就是方法的互相調(diào)用而已。
本文敘述下如何進行原生的JavaScript交互
本文包括JS調(diào)用OC方法并傳值仲器,OC調(diào)用JS方法并傳值
本來想把html放進服務(wù)器里面煤率,然后訪問,但是覺得如果html在本地加載更有助于理解乏冀,特把html放進項目里
HTML代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div style="margin-top: 20px">
<h2>JS與OC交互</h2>
<input type="button" value="喚起本地方法(call)" onclick="tianbai.call()">
</div>
<div>
<input type="button" value="喚起getCall:(NSString *)callString傳值" onclick="call()">
</div>
<script>
var call = function()
{
var callInfo = JSON.stringify({"jianshu": "http://www.reibang.com/users/55c8fdc3c6e7/latest_articles"});
tianbai.getCall(callInfo);
}
var Callback = function(str)
{
alert(str);
}
var alerCallback = function()
{
alert('成功');
}
</script>
</body>
</html>
上面html的代碼:建立了兩個button
第一個button綁定了 tianbai.call()
方法蝶糯,這里 tianbai
是一個對象,這個對象的作用下面OC代碼中會說明辆沦, tianbai.call()
代表 tianbai
對象調(diào)用 call()
方法
第二個button綁定了 call()
的方法昼捍,調(diào)用的是下面JavaScript中的 call()
方法,在 JavaScript 的 call()
里面肢扯,定義一個 callInfo
參數(shù)妒茬,方法中 tianbai.getCall(callInfo)
代表 tianbai
對象調(diào)用 getCall
方法并傳參數(shù) callInfo
,下面兩個方法是OC調(diào)用JavaScript方法蔚晨,其中Callback傳回str乍钻,alerCallback為OC僅調(diào)用JavaScript方法!
OC代碼
demo采用原生的JavaScriptCore類
引入三個名詞:
- JSContext:給JavaScript提供運行的上下文環(huán)境
- JSValue:JavaScript和Objective-C數(shù)據(jù)和方法的橋梁
- JSExport:這是一個協(xié)議,如果采用協(xié)議的方法交互团赁,自己定義的協(xié)議必須遵守此協(xié)議
ViewController.h中的代碼(代碼過長育拨,方法說明都在注釋里)
#import <UIKit/UIKit.h>
//導(dǎo)入頭文件
#import <JavaScriptCore/JavaScriptCore.h>
@protocol JSObjcDelegate <JSExport>
//tianbai對象調(diào)用的JavaScript方法,必須聲明;渡恪0旧ァ!
- (void)call;
- (void)getCall:(NSString *)callString;
@end
@interface ViewController : UIViewController<UIWebViewDelegate,JSObjcDelegate>
@property (nonatomic, strong) JSContext *jsContext;
@property (strong, nonatomic) UIWebView *webView;
@end
ViewController.m中的代碼(代碼過長怀挠,方法說明都在注釋里)
JavaScriptCore中web頁面調(diào)用原生應(yīng)用的方法可以用Delegate或Block兩種方法析蝴,此文以按Delegate講解。
設(shè)置webView
self.webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 20, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
self.webView.delegate = self;
//從本地加載html文件
NSString* path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSURL* url = [NSURL fileURLWithPath:path];
NSURLRequest* request = [NSURLRequest requestWithURL:url] ;
[self.webView loadRequest:request];
[self.view addSubview:self.webView];
JavaScript的tianbai是一個對象绿淋,充當(dāng)原生應(yīng)用和web頁面之間的一個橋梁闷畸。用來調(diào)用方法
webview加載完成調(diào)用代理
- (void)webViewDidFinishLoad:(UIWebView *)webView {
// 設(shè)置javaScriptContext上下文
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//將tianbai對象指向自身
self.jsContext[@"tianbai"] = self;
self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
context.exception = exceptionValue;
NSLog(@"異常信息:%@", exceptionValue);
};
}
將對象指向自身后,如果調(diào)用 tianbai.call()
會響應(yīng)下面的方法吞滞,OC方法中調(diào)用js中的Callback方法佑菩,并傳值
- (void)call{
NSLog(@"call");
// 之后在回調(diào)JavaScript的方法Callback把內(nèi)容傳出去
JSValue *Callback = self.jsContext[@"Callback"];
//傳值給web端
[Callback callWithArguments:@[@"喚起本地OC回調(diào)完成"]];
}
將對象指向自身后,如果調(diào)用 tianbai.getCall(callInfo)
會響應(yīng)下面的方法裁赠,OC方法中僅調(diào)用JavaScript中的alerCallback方法
- (void)getCall:(NSString *)callString{
NSLog(@"Get:%@", callString);
// 成功回調(diào)JavaScript的方法Callback
JSValue *Callback = self.jsContext[@"alerCallback"];
[Callback callWithArguments:nil];
}
將對象指向自身后殿漠,還可以向html注入js
- (void)alert{
// 直接添加提示框
NSString *str = @"alert('OC添加JS提示成功')";
[self.jsContext evaluateScript:str];
}
Demo地址:點擊下載