JSPath基础用法
2016-03-02 17:47
507 查看
1.require
2.调用OC方法
调用类方法
调用实例方法
参数传递
Property
方法名转换
3.特殊类型
Struct
Selector
nil
4.NSArray
/ NSString / NSDictionary
5.Block
block传递
block
里使用 self 变量
限制
6.__weak
/ __strong
7.GCD
8.传递
id* 参数
9.常量、宏、全局变量
常量
宏
全局变量
10.Swift
在使用Objective-C类之前需要调用
可以用逗号
或者直接在使用时才调用
跟在OC一样传递参数:
获取/修改 Property 等于调用这个 Property 的 getter / setter 方法,获取时记得加
多参数方法名使用
若原 OC 方法名里包含下划线
JS 使用双下划线
JSPatch原生支持 CGRect / CGPoint / CGSize / NSRange 这四个 struct 类型,用 JS 对象表示:
其他 Struct 类型的支持请参照 添加
struct 类型支持
在JS使用字符串代表 Selector:
nil
JS 上的
OC 的
用
NSArray / NSString / NSDictionary 不会自动转成对应的JS类型,像普通 NSObject 一样使用它们:
如果要把 NSArray / NSString / NSDictionary 转为对应的 JS 类型,使用
当要把 JS 函数作为 block 参数给 OC时,需要先使用
这里 block 里的参数类型用字符串表示,写上这个 block 各个参数的类型,用逗号分隔。NSObject 对象如
block 对象要用
从
OC 返回给 JS 的 block 会自动转为 JS function,直接调用即可:
若要把这个从 OC 传过来的 block 再传回给 OC,同样需要再用
JS function,跟我们上面定义的 JS function 没有区别:
总结:JS 没有 block 类型的变量,OC 的 block 对象传到 JS 会变成 JS function,所有要从 JS 传 block 给 OC
都需要用
在 block 里无法使用
从 JS 传 block 到 OC,有两个限制:
A. block 参数个数最多支持6个。(若需要支持更多,可以修改源码)
B. block 参数类型不能是
另外不支持 JS 封装的 block 传到 OC 再传回 JS 去调用(原因见 issue
#155):
可以在 JS 通过
例如我们在 OC 里为了避免 block 导致的循环引用,经常这样写:
在 JS 对应的可以这样写:
若要在使用 weakSelf 时把它变成 strong 变量,可以用
使用
如果你需要传递
这里传入的是一个指向 NSObject 对象的指针,在方法里可以修改这个指针指向的对象,调用后外部可以拿到新指向的对象,对于这样的参数,需要按以下步骤进行传递和获取:
使用
把指针作为参数传给方法
方法调用完,使用
使用完后调用
使用
举个例子:
Objective-C 里的常量不能直接在 JS 上使用,可以直接在 JS 上用具体值代替,或者在 JS 上重新定义同名的全局变量:
Objective-C 里的宏同样不能直接在 JS 上使用。若定义的宏是一个值,可以在 JS 定义同样的全局变量代替,若定义的宏是程序,可以在JS展开宏:
若宏的值是某些在底层才能获取到的值,例如
在类里定义的
使用
Swift 类时,类名应为
demo 里用 Swift 定义了 ViewController 类,在 JS 覆盖这个类方法时要这样写:
另外注意:Swift 类需要继承
NSObject,需要把要类/属性/方法等声明前面加上
注:OC转JS传送门http://bang590.github.io/JSPatchConvertor/
2.调用OC方法
调用类方法
调用实例方法
参数传递
Property
方法名转换
3.特殊类型
Struct
Selector
nil
4.NSArray
/ NSString / NSDictionary
5.Block
block传递
block
里使用 self 变量
限制
6.__weak
/ __strong
7.GCD
8.传递
id* 参数
9.常量、宏、全局变量
常量
宏
全局变量
10.Swift
1. require
在使用Objective-C类之前需要调用 require('className’):
require('UIView') var view = UIView.alloc().init()
可以用逗号
,分隔,一次性导入多个类:
require('UIView, UIColor') var view = UIView.alloc().init() var red = UIColor.redColor()
或者直接在使用时才调用
require():
require('UIView').alloc().init()
2. 调用OC方法
调用类方法
var redColor = UIColor.redColor();
调用实例方法
var view = UIView.alloc().init(); view.setNeedsLayout();
参数传递
跟在OC一样传递参数:var view = UIView.alloc().init(); var superView = UIView.alloc().init() superView.addSubview(view)
Property
获取/修改 Property 等于调用这个 Property 的 getter / setter 方法,获取时记得加 ():
view.setBackgroundColor(redColor); var bgColor = view.backgroundColor();
方法名转换
多参数方法名使用 _分隔:
var indexPath = require('NSIndexPath').indexPathForRow_inSection(0, 1);
若原 OC 方法名里包含下划线
_,在
JS 使用双下划线
__代替:
// Obj-C: [JPObject _privateMethod]; JPObject.__privateMethod()
3. 特殊类型
Struct
JSPatch原生支持 CGRect / CGPoint / CGSize / NSRange 这四个 struct 类型,用 JS 对象表示:// Obj-C UIView *view = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 100, 100)]; [view setCenter:CGPointMake(10,10)]; [view sizeThatFits:CGSizeMake(100, 100)]; CGFloat x = view.frame.origin.x; NSRange range = NSMakeRange(0, 1);
// JS var view = UIView.alloc().initWithFrame({x:20, y:20, width:100, height:100}) view.setCenter({x: 10, y: 10}) view.sizeThatFits({width: 100, height:100}) var x = view.frame().x var range = {location: 0, length: 1}
其他 Struct 类型的支持请参照 添加
struct 类型支持
Selector
在JS使用字符串代表 Selector://Obj-C [self performSelector:@selector(viewWillAppear:) withObject:@(YES)];
//JS self.performSelector_withObject("viewWillAppear:", 1)
nil
JS 上的
null和
undefined都代表
OC 的
nil,如果要表示
NSNull,
用
nsnull代替:
//Obj-C @implemention JPTestObject + (BOOL)testNull(NSNull *null) { return [null isKindOfClass:[NSNull class]] } @end
//JS require('JPTestObject').testNull(nsnull) //return 1 require('JPTestObject').testNull(null) //return 0
4. NSArray / NSString / NSDictionary
NSArray / NSString / NSDictionary 不会自动转成对应的JS类型,像普通 NSObject 一样使用它们://Obj-C @implementation JPObject + (NSArray *)data { return @[[NSMutableString stringWithString:@"JS"]] } + (NSMutableDictionary *)dict { return [[NSMutableDictionary alloc] init]; } @end
// JS require('JPObject') var ocStr = JPObject.data().objectAtIndex(0) ocStr.appendString("Patch") var dict = JPObject.dict() dict.setObject_forKey(ocStr, 'name') console.log(dict.objectForKey('name')) //output: JSPatch
如果要把 NSArray / NSString / NSDictionary 转为对应的 JS 类型,使用
.toJS()接口:
// JS var data = require('JPObject').data().toJS() //data instanceof Array === true data.push("Patch") var dict = JPObject.dict() dict.setObject_forKey(data.join(''), 'name') dict = dict.toJS() console.log(dict['name']) //output: JSPatch
5. Block
block 传递
当要把 JS 函数作为 block 参数给 OC时,需要先使用 block(paramTypes, function)接口包装:
// Obj-C @implementation JPObject + (void)request:(void(^)(NSString *content, BOOL success))callback { callback(@"I'm content", YES); } @end
// JS require('JPObject').request(block("NSString *, BOOL", function(ctn, succ) { if (succ) log(ctn) //output: I'm content }))
这里 block 里的参数类型用字符串表示,写上这个 block 各个参数的类型,用逗号分隔。NSObject 对象如
NSString *,
NSArray *等可以用
id表示,但
block 对象要用
NSBlock*表示。
从
OC 返回给 JS 的 block 会自动转为 JS function,直接调用即可:
// Obj-C @implementation JPObject typedef void (^JSBlock)(NSDictionary *dict); + (JSBlock)genBlock { NSString *ctn = @"JSPatch"; JSBlock block = ^(NSDictionary *dict) { NSLog(@"I'm %@, version: %@", ctn, dict[@"v"]) }; return block; } + (void)execBlock:(JSBlock)blk { } @end
// JS var blk = require('JPObject').genBlock(); blk({v: "0.0.1"}); //output: I'm JSPatch, version: 0.0.1
若要把这个从 OC 传过来的 block 再传回给 OC,同样需要再用
block()包装,因为这里
blk已经是一个普通的
JS function,跟我们上面定义的 JS function 没有区别:
// JS var blk = require('JPObject').genBlock(); blk({v: "0.0.1"}); //output: I'm JSPatch, version: 0.0.1
require('JPObject').execBlock(block("id", blk));
总结:JS 没有 block 类型的变量,OC 的 block 对象传到 JS 会变成 JS function,所有要从 JS 传 block 给 OC
都需要用
block()接口包装。
block 里使用 self 变量
在 block 里无法使用 self变量,需要在进入 block 之前使用临时变量保存它:
defineClass("JPViewController", { viewDidLoad: function() { var slf = self; require("JPTestObject").callBlock(block(function(){ //`self` is not available here, use `slf` instead. slf.doSomething(); }); } }
限制
从 JS 传 block 到 OC,有两个限制:A. block 参数个数最多支持6个。(若需要支持更多,可以修改源码)
B. block 参数类型不能是
double。
另外不支持 JS 封装的 block 传到 OC 再传回 JS 去调用(原因见 issue
#155):
- (void)callBlock:(void(^)(NSString *str))block { }
defineClass('JPTestObject', { run: function() { self.callBlock(block('NSString*', function(str) { console.log(str); })); }, callBlock: function(blk) { //blk 这个 block 是上面的 run 函数里 JS 传到 OC 再传过来的,无法调用。 blk("test block"); } });
6. __weak / __strong
可以在 JS 通过 __weak()声明一个 weak 变量,主要用于避免循环引用。
例如我们在 OC 里为了避免 block 导致的循环引用,经常这样写:
- (void)test { __weak id weakSelf = self; [self setCompleteBlock:^(){ [weakSelf blabla]; }] }
在 JS 对应的可以这样写:
var weakSelf = __weak(self) self.setCompleteBlock(block(function(){ weakSelf.blabla(); }))
若要在使用 weakSelf 时把它变成 strong 变量,可以用
__strong()接口:
var weakSelf = __weak(self) self.setCompleteBlock(block(function(){ var storngSelf = __strong(weakSelf) strongSelf.blabla(); }))
7. GCD
使用 dispatch_after()
dispatch_async_main()
dispatch_sync_main()
dispatch_async_global_queue()接口调用GCD方法:
// Obj-C dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // do something }); dispatch_async(dispatch_get_main_queue(), ^{ // do something });
// JS dispatch_after(1.0, function(){ // do something }) dispatch_async_main(function(){ // do something }) dispatch_sync_main(function(){ // do something }) dispatch_async_global_queue(function(){ // do something })
8. 传递 id*
参数
如果你需要传递 id*参数,像
NSURLConnection里的这个接口里的
NSError **:
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response
error:(NSError **)error;
这里传入的是一个指向 NSObject 对象的指针,在方法里可以修改这个指针指向的对象,调用后外部可以拿到新指向的对象,对于这样的参数,需要按以下步骤进行传递和获取:
使用
malloc(sizeof(id))创建一个指针
把指针作为参数传给方法
方法调用完,使用
pval()拿到指针新指向的对象
使用完后调用
releaseTmpObj()释放这个对象
使用
free()释放指针
举个例子:
//OC - (void)testPointer:(NSError **)error { NSError *err = [[NSError alloc]initWithDomain:@"com.jspatch" code:42 userInfo:nil]; *error = err; }
//JS //malloc() pval() free() is provided by JPMemory extension require('JPEngine').addExtensions(['JPMemory']) var pError = malloc(sizeof("id")) self.testPointer(pError) var error = pval(pError) if (!error) { console.log("success") } else { console.log(error) } releaseTmpObj(pError) free(pError)
9. 常量、宏、全局变量
常量
Objective-C 里的常量不能直接在 JS 上使用,可以直接在 JS 上用具体值代替,或者在 JS 上重新定义同名的全局变量://js var UIRectEdgeNone = 0, UIRectEdgeTop = 1 << 0, UIRectEdgeLeft = 1 << 1, UIRectEdgeBottom = 1 << 2, UIRectEdgeRight = 1 << 3
宏
Objective-C 里的宏同样不能直接在 JS 上使用。若定义的宏是一个值,可以在 JS 定义同样的全局变量代替,若定义的宏是程序,可以在JS展开宏:#define TABBAR_HEIGHT 40 #define SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.height
//JS //instead of var tabbarHeight = TABBAR_HEIGHT var tabbarHeight = 40; //instead of var width = SCREEN_WIDTH var width = UIScreen.mainScreen().bounds().height;
若宏的值是某些在底层才能获取到的值,例如
CGFLOAT_MIN,可以通过在某个类或实例方法里将它返回,或者用添加扩展的方式提供支持:
@implementation JPMacroSupport + (void)main:(JSContext *)context { context[@"CGFLOAT_MIN"] = ^CGFloat() { return CGFLOAT_MIN; } } @end
require('JPEngine').addExtensions(['JPMacroSupport']) var floatMin = CGFLOAT_MIN();
全局变量
在类里定义的 static全局变量无法在 JS 上获取到,若要在 JS 拿到这个变量,需要在 OC 有类方法或实例方法把它返回:
static NSString *name; @implementation JPTestObject + (NSString *)name { return name; } @end
var name = JPTestObject.name() //拿到全局变量值
10. Swift
使用 defineClass()覆盖
Swift 类时,类名应为
项目名.原类名,例如项目
demo 里用 Swift 定义了 ViewController 类,在 JS 覆盖这个类方法时要这样写:
defineClass('demo.ViewController', {})
另外注意:Swift 类需要继承
NSObject才能被调用和替换,若不是继承
NSObject,需要把要类/属性/方法等声明前面加上
@objc修饰符,详见这里。
注:OC转JS传送门http://bang590.github.io/JSPatchConvertor/
相关文章推荐
- js倒计时代码 适合于促销-倒计时代码
- 详细介绍Jsp中的Cookies
- 关于jsp的九大隐式
- jsp 获取cookie 的值的方法
- jsp创建cookie
- JSP中如何设置Cookies
- JSP Cookie 使用完全详解
- javascript 要点总结
- anjularjs弹出model(模态框)
- jsp的9大隐式对象的使用总结
- js 促销倒计时
- 通过Canvas + JS 实现简易时钟实战
- JavaScript中读取和保存文件实例
- JMeter中对于Json数据的处理方法
- javascript高级程序设计笔记-第七章(函数表达式)
- 文本框只允许输入数字.net/javascript
- 如何销毁js的变量啊?
- JSON解析---初识
- js 搜索关键字,文章中关键字高亮显示
- jsp常用动作