如何使用Objective-C 呼叫 JavaScript - Part I 基礎篇
之前工作需要在ios上開發Ethereum 類電子錢包的SDK,(離線狀態)做交易的打包,簽章,呼叫ABI等等之類的,Geth, ethereum.io都有部分達不到我們需求的地方,最後採用Web3.js
Objective-C經驗不是很多,JavaScript根本就不會,所以在找solution的過程,吃了不少苦頭。找了不少資料,看到的都是透過這兩種方式呼叫
- WebView:JavaScript是寫在html裡的,所以需要多一個html檔案
- JavaScriptCore:直接呼叫 .js檔案,類似node.js的方式,比較直接
網路上的範例大概都長得像這個樣子,直接把功能寫在html裡
<html>
<head>
<script>
function myFunction()
{
alert("Hello World!");
}
</script>
</head>
<body>
<button onclick="myFunction()">Try me</button>
</body>
</html>
Objective-C的部分大概長得像這樣,一定要在有UI的檔案裡
// @implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 先取得html檔案路徑,使用webview loads html
NSBundle *thisBundle = [NSBundle mainBundle];
NSString *path = [thisBundle pathForResource:@"first" ofType:@"html"];
NSURL *instructionsURL = [NSURL fileURLWithPath:path];
UIWebView* webView = [[UIWebView alloc] init];
[webView loadRequest:[NSURLRequest requestWithURL:instructionsURL]];
// 然後呼叫 js 的function, 最後的()是需要的喔!!
[webView stringByEvaluatingJavaScriptFromString:@"myFunction()"];
}
那...如果需要帶參數怎麼辦勒?!
假設你的js function長這樣
<html>
<head>
<script>
function myFunction(msg)
{
alert("Hello " + msg);
}
</script>
</head>
<body>
<button onclick="myFunction()">Try me</button>
</body>
</html>
那Obj-C最後在呼叫函數的部分就變成
// 然後呼叫 js 的function
[webView stringByEvaluatingJavaScriptFromString:@"myFunction('Kimi')"];
那...如果,參數多一點,結構複雜一點勒?! 這種方式寫起來很麻煩,而且很容易忘記要加'()'
我個人是比較喜歡另一種方式,由JavaScriptCore幫開發者包裝參數部分
javascript檔案
"use strict"
// 這裡就不要用alert囉,因為他不會理你,懂前端的人應該就不會犯這種很笨的錯 XD
function myJSFunction(a, b) {
return a+b;
}
Obj-C// 需要import JavaScriptCore
#import <JavaScriptCore/JavaScriptCore.h>
// 先把 js的檔案載入
JSContext* jsContext = [[JSContext alloc] init];
NSURL *scriptURL = [NSURL URLWithString:@"myJavaScript.js"];
NSString *script = [NSString stringWithContentsOfURL:scriptURL encoding:NSUTF8StringEncoding error:nil];
[jsContext evaluateScript:script];
// 呼叫 js 的funciton
JSValue *jsValue = jsContext[@"myJSFunction"];
//NSLog(@"%@", [jsValue toString]); //這行會show出myJSFunction的內容
[jsValue
callWithArguments:@[1,2]];
對於不熟前端的人來說,這樣是不是親切許多,不需要再去多寫一個html檔案,而且傳參數方便多了(不會有單引號 雙引號的問題)原則上,Obj-C怎麼呼叫JS大概就介紹完畢了,好像很簡單對不對。對!沒錯。不過...在真實世界的狀況,哪有這麼簡單,讓你去呼叫 js 的 alert就好,以我的例子,就是需要呼叫一整個函式庫,程式碼就會分檔案,就會需要import/include/require其他的檔案,以我的例子,Web3.js裡的index.js,一開頭就是一堆的require。
"use strict";
var version = require('../lerna.json');
var core = require('../packages/web3-core');
var Eth = require('../packages/web3-eth');
var Net = require('../packages/web3-net');
var Personal = require('../packages/web3-eth-personal');
var Shh = require('../packages/web3-shh');
var Bzz = require('../packages/web3-bzz');
var utils = require('../packages/web3-utils');
var version = require('../lerna.json');
var core = require('../packages/web3-core');
var Eth = require('../packages/web3-eth');
var Net = require('../packages/web3-net');
var Personal = require('../packages/web3-eth-personal');
var Shh = require('../packages/web3-shh');
var Bzz = require('../packages/web3-bzz');
var utils = require('../packages/web3-utils');
如果你用上述的作法,就會碰到'ReferenceError: Can't find variable: require' 的錯誤,至於這個的解法尋找了很久,似乎很少人遇到這樣的問題,或是說很少人有這樣的需求。
因為篇幅過長,所以Part II 實戰篇繼續介紹!
ref:
https://stackoverflow.com/questions/14334047/how-to-call-javascript-function-in-objective-c
https://stackoverflow.com/questions/23508455/call-native-objective-methods-from-javascript-using-javascript-core-framework
留言
張貼留言