Swift:CFArray:将值作为UTF字符串获取

时间:2015-12-06 17:01:03

标签: string swift utf-8

我调用一些返回CFArray CFStringRef个值的函数。我需要从他们那里得到utf字符串。由于我不想让我的代码太复杂,我做了以下几点:

let initString = "\(TISCreateInputSourceList(nil, false).takeUnretainedValue())"

然后我只是将结果字符串分割为\n来获取一个Swift字符串数组。但是,当函数开始返回非ascii字符串时,启动了麻烦。我开始得到像“\ U2345 \ U2344”这样的字符串。

然后我尝试接受CFArray并迭代它获取值并可能将它们转换为字符串,但我无法从中获取值:

        let ar = TISCreateInputSourceList(nil, true).takeUnretainedValue()
        for i in 0...CFArrayGetCount(ar) - 1 {
            print(">> ( CFArrayGetValueAtIndex(ar, i).memory )")
        }

值始终为空。

我如何获得实际值?

1 个答案:

答案 0 :(得分:8)

这里有一些问题。首先,TISCreateInputSourceList() 已经"创造"在其名称中,这意味着它返回保留的(+1) 对象,您必须使用takeRetainedValue()取值, 不是takeUnretainedValue(),否则代码会泄漏内存:

let srcs = TISCreateInputSourceList(nil, true).takeRetainedValue()

您现在可以使用CFArray...方法从数组中获取值, 但将它转换为NSArray(即#34;免费桥接")更容易:

let srcs = TISCreateInputSourceList(nil, true).takeRetainedValue() as NSArray

这不是CFStringRef值的数组,而是一个数组 TISInputSource个对象。您可以将NSArray转换为Swift数组:

let srcs = TISCreateInputSourceList(nil, true).takeRetainedValue()
                    as NSArray as! [TISInputSource]

强制转换as!在这里是可以接受的,因为函数是 记录以返回一组输入源。

现在您可以简单地遍历数组的元素:

for src in srcs  {
    // do something with `src` (which is a `TISInputSource`)
}

使用TISGetInputSourceProperty()函数检索输入源的属性,例如:

let ptr = TISGetInputSourceProperty(src, kTISPropertyInputSourceID)

这会返回一个&#34; void指针&#34; (UnsafeMutablePointer<Void>)必须转换为对象 适当类型的指针(CFStringRefkTISPropertyInputSourceID财产)。不幸的是,这有点 复杂(比较How to cast self to UnsafeMutablePointer<Void> type in swift):

let val = Unmanaged<CFString>.fromOpaque(COpaquePointer(ptr)).takeUnretainedValue()

我们再次利用免费桥接,现在来自 CFStringRefNSStringString

let val = Unmanaged<CFString>.fromOpaque(COpaquePointer(ptr)).takeUnretainedValue()
                    as String

全部放在一起:

let srcs = TISCreateInputSourceList(nil, true).takeRetainedValue()
                as NSArray as! [TISInputSource]
for src in srcs  {
    let ptr = TISGetInputSourceProperty(src, kTISPropertyInputSourceID)
    let val = Unmanaged<CFString>.fromOpaque(COpaquePointer(ptr)).takeUnretainedValue()
                as String
    print(val)
}