美文网首页
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