JSPatch常见问题

1.字符串/数组/字典操作问题#

刚使用 JSPatch 经常会对 NSString / NSArray / NSDictionary / NSDate 这四个类的使用感到迷惑,因为 JS 语言本身有对应的这四个类型,会跟 OC 的这四个类混淆。要避免混淆,要弄清楚两点:
1.需要认清这四个类有 JS 跟 OC 两种类型

//OC
@implementation JPTestObject
+ (NSString *)name {
  return @"I'm NSString";
}
+ (NSMutableDictionary *)info {
  return @{@"k": @"v"};
}
+ (NSArray *)users {
  return @[@"alex", @"bang", @"cat"];
}
@end
var ocStr = JPTestObject.name();
var ocInfo = JPTestObject.info();
var ocUsers = JPTestObject.users();

//以上三个是从 OC 返回的 OC 对象,可以调用 OC 方法:
ocStr.rangeOfString("I'm");   //OK
ocInfo.addObject_forKey("a", "b");   //OK
ocUsers.firstObject();    //OK

///////////////////////////////////////

var str = "I'm JS String";
var info = @{"k": "v"};
var users = ["alex", "bang", "cat"];

//以上三个是 JS 对象,不能调用 OC 方法:
str.rangeOfString("I'm");   //crash
info.addObject_forKey("a", "b");   //crash
users.firstObject();    //crash

2.若要用JS语法操作这些类型,要确保它是 JS 对象。

//错误:ocStr 不是 JS 对象,不能用 JS 语法拼接字符串
var newStr = ocStr + "js string";   

//正确:已用 .toJS() 接口转为 JS 对象,可以用 JS语法操作
var transStr = ocStr.toJS();
var newStr = transStr + "js string";  


//错误:ocUsers 不是 JS 对象,不能用[]语法,也不能用 JS 语法遍历
var firstUser = ocUser[0];
for (var i = 0; i < ocUsers.length; i ++) {
  var user = ocUsers[i];
}

//正确:已用 .toJS() 接口转为 JS 对象,可以用 JS语法操作
var transArr = ocUsers.toJS();
var firstUser = transArr[0];
for (var i = 0; i < transArr.length; i ++) {
  var user = transArr[i];
}


//错误: ocInfo 不是 JS 对象,不能用[]语法
var v = ocInfo['k'];

//正确:已用 .toJS() 接口转为 JS 对象,可以用 JS语法操作
var transDict = ocInfo.toJS();
var v = transDict['k'];

stringWithFormat#

JSPatch 支持调用 stringWithFormat,不过所有参数类型都需改为 %@:

//OC
[NSString stringWithFormat:@"name:%@, age:%d", @"alex", 12];
//JS
NSString.stringWithFormat("name:%@, age:%@", "alex", 12);

虽然支持 stringWithFormat,但还是建议使用 JS 语法拼接字符串:

var ret = "name:" + "alex" + " age:(" + 12 + ")";

NSNumber#

NSNumber 与上述四个类型不一样,所有数值类型以及 NSNumber 对象到 JS 后都会变成数值,不能再调用这个数值的任何方法:

//OC
@implementation JPTestObject
+ (NSNumber *)returnNSNumber {
    return @(42);
}
+ (int)returnInt
{
  return 42;
}
@end
var numFromOC = JPTestObject.returnNumber()
var intFromOC = JPTestObject.returnInt()
var jsNum = 42

//以上三个变量是相等的:
console.log(numFromOC == intFromOC == jsNum) //true

//不能调用 NSNumber 方法:
numFromOC.isEqualToNumber(42);  //crash

//所有数值操作都应该在 JS 语法下操作:
parseInt(numFromOC);
var all = numFromOC + intFromOC + jsNum;

for...in#

首先从 OC 返回的 NSArray / NSDictionary 对象是不能直接用 for...in 遍历的,需要调用 .toJS()
后才能进行遍历,详情见上文。
然后在遍历数组时,JavaScript 的 for...in 语法定义与 Objective-C 不同:

//OC
NSArray *arr = @[@"name", @"age"];
for (var o in arr) {
  NSLog(@"%@", o); //输出 name age
}
var arr = ["name", "age"];
for (var o in arr) {
  console.log(o); //输出 0, 1,表示遍历数组的序号
  console.log(arr[o]); //输出 name age,这样才表示数组的值
}

Block相关问题#

若使用 block 时出现 crash,最常见的原因是在 block 里使用了 self
变量,应该在 JS 声明另一个变量持有 self

defineClass("JPViewController", {
  viewDidLoad: function() {
    var slf = self;
    require("JPTestObject").callBlock(block(function(){
      //`self` is not available here, use `slf` instead.
      slf.doSomething();
    });
  }
}

Property和私有成员变量#

获取/修改 Property 等于调用这个 Property 的 getter / setter 方法,获取时记得加 ():

view.setBackgroundColor(redColor);
var bgColor = view.backgroundColor();

使用 valueForKey() 和 setValue_forKey() 获取/修改私有成员变量:

// OC
@implementation JPTableViewController { 
    NSArray *_data;
}
@end

// JS
defineClass("JPTableViewController", {
  viewDidLoad: function() {
     var data = self.valueForKey("_data")     //get member variables
     self.setValue_forKey(["JSPatch"], "_data")     //set member variables
  },
})

调试#

可以使用 console.log()打印一个对象,作用相当于 NSLog(),会直接在 XCode 控制台打出。

var view = UIView.alloc().init();
var str = "test";
var num = 1;
console.log(view, str, num)
console.log(str + num);   //直接在JS拼接字符串

也可以通过 Safari 的调试工具对 JS 进行断点调试,详见 JS 断点调试
例如可以在控制台打印OC对象 :

url.__c("toJS")()

未完,待续......

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容