美文网首页
JSPatch常见问题

JSPatch常见问题

作者: Mr_Baymax | 来源:发表于2016-10-20 20:30 被阅读147次

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")()

未完,待续......

相关文章

网友评论

      本文标题:JSPatch常见问题

      本文链接:https://www.haomeiwen.com/subject/dkfquttx.html