我调用一些返回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 )")
}
值始终为空。
我如何获得实际值?
答案 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>
)必须转换为对象
适当类型的指针(CFStringRef
为
kTISPropertyInputSourceID
财产)。不幸的是,这有点
复杂(比较How to cast self to UnsafeMutablePointer<Void> type in swift):
let val = Unmanaged<CFString>.fromOpaque(COpaquePointer(ptr)).takeUnretainedValue()
我们再次利用免费桥接,现在来自
CFStringRef
到NSString
和String
:
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)
}