iOS javascript與object-c的互動(TSY版本-就是本人)

PeachRain發表於2017-12-14

一:前言

      有於本人對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的關係更緊密.


其它的請自行檢視程式碼,說一堆廢話不如直接上程式碼(其實是樓主懶)。


相關文章