我们如何从 OS X JXA 中读取/强制 CFArray 和 CFString 等值?

How can we reading / coerce CFArray and CFString etc values from within OS X JXA?

如果您通过 ObjC 桥试验 reading/setting OSX 输入语言,编写如下代码片段:

(function () {
    'use strict';

    ObjC.import('Carbon');
    ObjC.import('stdio');

    var sourceList = $.TISCreateInputSourceList(null, false);

    var current_source = $.TISCopyCurrentKeyboardInputSource();

    var cfs = $.TISGetInputSourceProperty(current_source, $.kTISPropertyInputSourceID);
    var cfn = $.TISGetInputSourceProperty(current_source, $.kTISPropertyLocalizedName)

    var sourceCount = $.CFArrayGetCount(sourceList)

    return $.CFArrayGetValueAtIndex(sourceList, 0)

})();

我们很快就会得到 CF 类型的对象引用 return 值。在 ObjC 本身中,这些可以强制转换为 NS 值。在 JavaScript for Applications 中如何实现这一目标?

(我正在获取 CF 对象引用 return 值,但我无法从中成功提取字符串或其他原始值)

您可以通过首先 re-binding CFMakeCollectable 函数将 CF 类型强制转换为 NS 类型,这样它需要 'void *' 和 returns 'id',然后使用它执行强制转换的函数:

ObjC.bindFunction('CFMakeCollectable', [ 'id', [ 'void *' ] ]);

var cfString = $.CFStringCreateWithCString(0, "foo", 0); // => [object Ref]
var nsString = $.CFMakeCollectable(cfString);            // => $("foo")

为了使其更易于在您的代码中使用,您可以在 Ref 原型上定义一个 .toNS() 函数:

Ref.prototype.toNS = function () { return $.CFMakeCollectable(this); }

以下是如何将这个新函数与 TIS* 函数一起使用:

ObjC.import('Carbon');

var current_source = $.TISCopyCurrentKeyboardInputSource();
var cfs = $.TISGetInputSourceProperty(current_source, $.kTISPropertyInputSourceID);

cfs.toNS() // => $("com.apple.keylayout.US")