http://blog.csdn.net/zfpp25_/article/details/9232129
http://blog.csdn.net/zfpp25_/article/details/9236357
IOS7之前,接觸 JS 更多的是處理UIWebView的時候,如:http://blog.csdn.net/zfpp25_/article/details/8650412
但IOS7引入了JS框架<JavaScriptCore/JavaScriptCore.h>,給了“純IOS程序員”一個枯木逢春的契機~學習強大的 JavaScript。
1、 基本概念
JavaScriptCore.framework :iOS7 中新加入的框架,用來處理JavaScript。JavaScriptCore 是蘋果 Safari 瀏覽器的 JavaScript 引擎,JavaScriptCor在 OS X 平臺上很早就存在的,而在 iOS 平臺,直到IOS7纔對外開放,並提供了 Objective-C 的接口。
2、主要內容
• Objective-C → JavaScript
• JavaScript → Objective-C
• Memory management
• Threading
• JavaScriptCore C API
• JavaScriptCore with a WebView
首先引入框架 #import <JavaScriptCore/JavaScriptCore.h>
一、Objective-C → JavaScript
瞭解下面幾個類:
JSContext:An instance of JSContext represents a JavaScript execution environment.(一個 Context 就是一個 JavaScript 代碼執行的環境,也叫作用域。)
JSValue:Conversion between Objective-C and JavaScript types.(JS是弱類型的,ObjectiveC是強類型的,JSValue被引入處理這種類型差異,在 Objective-C 對象和 JavaScript 對象之間起轉換作用)
Objective-C 和 JavaScript 中類型的對照表:
實例代碼:1
int main() {
JSContext *context = [[JSContextalloc]init];
JSValue *result = [context evaluateScript:@"2 + 2"];
NSLog(@"2 + 2 = %d", [result toInt32]);
return 0;
}
實例代碼:2
(1)新建一個test.js文件,其中實現代碼:
//計算階乘
var factorial = function(n) {
if (n < 0)
return;
if (n === 0)
return 1;
return n * factorial(n - 1)
};
(2)調用時實現代碼:
- (void) factorial
{
NSString *path = [[NSBundlemainBundle]pathForResource:@"test"ofType:@"js"];
NSString *testScript = [NSStringstringWithContentsOfFile:pathencoding:NSUTF8StringEncodingerror:nil];
JSContext *context = [[JSContextalloc]init];
[context evaluateScript:testScript];
JSValue *function = context[@"factorial"];
JSValue *result = [function callWithArguments:@[@10]];
NSLog(@"factorial(10) = %d", [resulttoInt32]);
}
這樣就計算出了10的階乘。
注意:如果運行結果不正確,注意js文件是否已經加到項目的Buddle Resources中
二、JavaScript → Objective-C
• Two ways to interact with Objective-C from JavaScript (可以通過兩種方式在 JavaScript 中調用 Objective-C)
■ Blocks :JS functions (對應 JS 函數)
■ JSExport protocol :JS objects (對應 JS 對象)
(1)Blocks
- (void) testMakeUIColor
{
JSContext *context = [[JSContextalloc]init];
context[@"creatUIColor"] = ^(NSDictionary *rgbColor){
return [UIColor colorWithRed:([rgbColor[@"red"] floatValue] /255.0)
green:([rgbColor[@"green"]floatValue] /255.0)
blue:([rgbColor[@"blue"]floatValue] /255.0)
alpha:1];
};
JSValue *color = [contextevaluateScript:@"makeUIColor({red: 150, green: 150, blue: 200})"];
NSLog(@"color:%@",[colortoObject]);
}
注意:
1、Avoid capturing JSValues, Prefer passing as arguments.(不要在 Block 中直接使用外面的 JSValue 對象, 把 JSValue 當做參數來傳進 Block 中。)
2、Avoid capturing JSContexts, Use + [JSContext currentContext] (避免循引用,不要在 Block 中直接引用使用外面的 JSContext 對象,應該用[JSContext currentContext];)
錯誤的做法:
正確的做法:
(2)JSExport protocol
首先引入
#import <objc/runtime.h>
實例代碼1: JS代碼設置Button 的 title
@protocol UIButtonExport <JSExport>
- (void)setTitle:(NSString *)title forState:(UIControlState)state;
@end
- (void) test
{
class_addProtocol([UIButtonclass],@protocol(UIButtonExport));
UIButton *button = [UIButtonbuttonWithType:UIButtonTypeSystem];
[button setTitle:@"Hello Objective-C"forState:UIControlStateNormal];
button.frame = CGRectMake(20,40,280,40);
JSContext *context = [[JSContextalloc]init];
context[@"button"] = button;
[context evaluateScript:@"button.setTitleForState('Hello JavaScript', 0)"];
[self.view addSubview:button];
}
說明:
上面代碼中,我們申明一個 UIButtonExport 協議,該協議繼承於 JSExport,並將setTitle:forState:方法開放到該協議中(只有 JSExport 協議中的方法才能被 JavaScript 識別),然後通過運行時讓 UIButton 遵循 UIButtonExport 協議。這樣你就可以在 JS 中爲 Button 設置 title 了,需要說明一點的是,在 JS 中方法的命名規則與 Objective-C 中有點不一樣,如 Objective-C 中的方法-(void)setX:(id)x
Y:(id)y Z:(id)z;,加入到 JSExport 協議中,在 JS 中調用就得是setXYZ(x, y, z);,當然如果你不想根據這種命名轉換規則,你也可以通過 JSExport.h 中的方法來修改:
#define JSExportAs(PropertyName, Selector) \
@optional Selector __JS_EXPORT_AS__##PropertyName:(id)argument; @required Selector
#endif
如 setX:Y:Z 方法,我們可以給他重命名,讓 JS 中通過 set3D(x,y,z) 來調用
- (void)setX:(id)x Y:(id)y Z:(id)z
);
實例代碼2:
a、新建類 NativeObject,代碼實現L:
.h代碼:
#import <Foundation/Foundation.h>
@import JavaScriptCore;
@protocol NativeObjectExport <JSExport>
-(void)log:(NSString*)string;
@end
@interface NativeObject : NSObject <NativeObjectExport>
@end
.m代碼:
#import "NativeObject.h"
@implementation NativeObject
-(void)log:(NSString*)string {
NSLog(@"js: %@", string);
}
@end
調用代碼:
- (void) testLog
{
JSContext *context = [[JSContextalloc]init];
context[@"nativeObject"] = [[NativeObjectalloc]init];
[context evaluateScript:@"nativeObject.log(\"Hello Javascript\")"];
}
其它: