一:前言
有於本人對html,web網頁製作比較感興趣,所以身為ios程式設計師的我不務正業的看起了js,css,html,jq等的相關資訊,發現了一片新大陸啊,可惜本人學業不精只能學到一點皮毛。
由於最近web相關的都比較火,所以也開始研究了下ios與js的相關的一些通訊互動,但是研究的比較淺,寫寫微博,這樣自己就也能記得住。
我的簡易的demo: https://github.com/taosiyu/TSYJavaScriptCoreDemo 請大家點個星星啊
二:關於javaScriptCore
iOS7以後蘋果加入了JavaScriptCore.framework的框架。把 WebKit 的 JavaScript 引擎用 Objective-C 封裝。讓Objective-C和JavaScript程式碼的互動變得簡單方便。至於ios7之前的方法框架由於現在ios7之前的機器較少而且利用擷取方式呼叫感覺不怎麼高大上,所以直接忽略,如果硬要了解請檢視樓底的分享連結。
JSContext和JSValue
JSVirtualMachine為JavaScript的執行提供了底層資源,JSContext就為其提供著執行環境,通過- (JSValue *)evaluateScript:(NSString *)script;方法就可以執行一段JavaScript指令碼,並且如果其中有方法、變數等資訊都會被儲存在其中以便在需要的時候使用。而JSContext的建立都是基於JSVirtualMachine:- (id)initWithVirtualMachine:(JSVirtualMachine *)virtualMachine;,如果是使用- (id)init;進行初始化,那麼在其內部會自動建立一個新的JSVirtualMachine物件然後呼叫前邊的初始化方法。
JSValue則可以說是JavaScript和Object-C之間互換的橋樑,它提供了多種方法可以方便地把JavaScript資料型別轉換成Objective-C,或者是轉換過去。
JSContext 可以通過[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];來獲取js環境
當然在使用框架之前首先要匯入標頭檔案
#import<JavaScriptCore/JavaScriptCore.h>
然後再載入html頁面
在頁面載入完成之後
- (void)webViewDidFinishLoad:(UIWebView *)webView{
//獲取js的環境,在這裡獲取是為了避免頁面沒有載入完成導致oc調不到 js的方法
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 列印異常,由於JS的異常資訊是不會在OC中被直接列印的,所以我們在這裡新增列印異常資訊,
self.context.exceptionHandler =
^(JSContext *context, JSValue *exceptionValue)
{
context.exception = exceptionValue;
NSLog(@"%@", exceptionValue);
}
}
JS --------呼叫------>OC
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
// 以 html title 設定 導航欄 title
self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
// Undocumented access to UIWebView's JSContext
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 列印異常
self.context.exceptionHandler =
^(JSContext *context, JSValue *exceptionValue)
{
context.exception = exceptionValue;
NSLog(@"%@", exceptionValue);
};
// 以 JSExport 協議關聯 native 的方法
self.context[@"app"] = self;
// 以 block 形式關聯 JavaScript function
self.context[@"log"] =
^(NSString *str)
{
NSLog(@"%@", str);
};
self.context[@"wowowowow"] =
^(NSString *str)
{
NSLog(@"============================>>>>>>>>>>>>>%@",str);
};
// 以 block 形式關聯 JavaScript function
self.context[@"alert"] =
^(NSString *str)
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"msg from js" message:str delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
[alert show];
};
__block typeof(self) weakSelf = self;
self.context[@"addSubView"] =
^(NSString *viewname)
{
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(10, 500, weakSelf.view.frame.size.width, 100)];
view.backgroundColor = [UIColor redColor];
[weakSelf.view addSubview:view];
};
//多引數
self.context[@"mutiParams"] =
^(NSString *a,NSString *b,NSString *c)
{
NSLog(@"%@ %@ %@",a,b,c);
};
[self.context evaluateScript:@"var squareFunc = function(value) { return value * 2 }"];
JSValue *S = [self.context evaluateScript:@"squareFunc(10)"];
NSLog(@"tonumber = %@",S.toNumber);
}
主要是看看js呼叫oc的方法比以前用擷取的方法方便很多,也更符合mvc的思想,讓js和oc的關係更緊密.
其它的請自行檢視程式碼,說一堆廢話不如直接上程式碼(其實是樓主懶)。