1.3.7 用JS使用原生API
概览
NativeScript允许你从底层平台使用所有原生API。要完成这个行为,后台将发生很多事情。其中之一是 marshalling ?编组?编译?——JS与IOS的 Objective-C 数据类型和 Android 的Java数据类型之间的转换。
本文中,你将学习如何通过JS使用不同的数据类型参数来调用原生API。更多信息,参看 iOS Runtime 和 Android Runtime 章节的有关数据转换的具体平台资源。
数字型
当地原生的数值类型(例如,IOS的char,int,float,double 和 Android的 byte, short, int, long, double, float )都将被隐式地转换为JavaScript的数值,反之亦然。例如,当你在IOS上运行下面的代码:
// iOS
console.log('pow(2.5, 3) = ', pow(2.5, 3));
iOS Runtime将转换JS数字字面量为原生的 double类型,并把它们传递给原生函数 pow(double x, double y)
。返回的原生整形将自动地转换为JS数字并传递给 console.log()
。这在 Android 上同样有效:
// Android
console.log('min(3, 4) = ', java.lang.Math.min(3, 4));
原生的 java.lang.Math.min()
要求有两个整形。 Android Runtime 知道 java.lang.Math.min()
的签名并将字面量3和4用JAVA整形数据类型翻译成它们的表述。返回的整形同样也自动地翻译成JS数字并传递给 console.log()
。
类和对象
所有原生的类在JS世界里由一个构造函数代表。一个原生类里的每一个静态方法在JS构造函数之上成为一个函数,且每个实例方法在JS原型之上成为一个函数。在IOS上执行这段代码:
// iOS
var array = new NSMutableArray();
array.addObject(new NSObject());
iOS Runtime调用 [[NSMutableArray alloc] init]
且返回的原生对象被转换为JS对象包装器并指派为 array1
。该包装器拥有 NSMutableArray
(及其前身)的原型链上的所有实例方法,所以它们可以从JS调用。为了从JS里使用更方便,方法名轻微地有所改变(比如 tObject:atIndexedSubscript:
在JS里命名为 setObjectAtIndexedSubscript()
)。 Android 里同样有效:
// Android var context = ...;
var button = new android.widget.Button(context);
button.setText("My Button");// "My Button" is converted to java.lang.String
字符串
JavaScript 字符串在Android上隐式地整理成 java.lang.String
, 在IOS上是NSString
,反之亦然。
// iOS
var button = new UIButton();
button.setTitleForState('Button title', UIControlStateNormal); // 'Button title' 转换成 NSString
console.log(button.titleLabel.text); // 返回的 NSString 转换成 JavaScript string
// Android
var file = new java.io.File('myfile.txt'); // 'myfile.txt' 转换成 java.lang.String
这里有个例外是 NSString
类之上声明作为返回的 instancetype
的方法——初始化方法和工厂方法。这意味着对 NSString.stringWithString
的调用,其在 Objective-C里的返回类型是 instancetype
,将返回一个包装器,外面包裹着一个 NSString
实例,相对JS字符串而言。
例外:
在
NSString
类之上声明作为返回的instancetype
的方法 (如,初始化方法和工厂方法) 。例如,对NSString.stringWithString
的调用在 Objective-C 里结果是返回instancetype
。在你的 NativeScript 代码里,类似的调用会返回包裹着一个NSString
实例的包装器而替代JS字符串。
布尔型
JavaScript boolean values are implicitly marshalled to boolean
on Android and BOOL
on iOS and vice versa.
JS的 boolean 值隐式地整理成 Android 的 boolean
和IOS的 BOOL
,反之亦然。
// iOS
var str = NSString.stringWithString('YES');
var isTrue = str.boolValue();
// Android
var str = new java.lang.String('Hello world!');
var result = str.endsWith('world!');
console.log(result); // true
数组
JS数组映射为专门的 Android 上的Java数组和IOS上的 NSArray
。
// iOS
// nsArray is not a JavaScript array but a JavaScript wrapper around a native NSArray
var nsArray = NSArray.arrayWithArray(['Four', 'Five', 'Two', 'Seven']);
var jsArray = ['One', 'Two', 'Three'];
// pure JavaScript array
var firstCommon = nsArray.firstObjectCommonWithArray(jsArray);
console.log(firstCommon); // Two
The following code snippet shows how to call a ns.example.Math.minElement(int[] array)
from JavaScript:
下面的代码片段显示了如何从 JS 调用一个 ns.example.Math.minElement(int[] array)
:
// Android
var numbers = [3, 6, 19, -2, 7, 6];
var min = ns.example.Math.minElement(numbers); // -2
Undefined & Null
JavaScript Undefined & Null 映射为 Java null 指针 ,而 Objective-C nil.的原生 null 值映射为 JavaScript null.
// iOS
console.log(NSStringFromClass(null)); // null
// Android
var context = ...;
var button = new android.widget.Button(context);
button.setOnClickListener(undefined); // the Java call will be made using the null keyword
也可参考
- Marshalling in Android Runtime
- Marshalling in iOS Runtime