【问题标题】:Swift: CFArray : get values as UTF StringsSwift:CFArray:获取值作为 UTF 字符串
【发布时间】:2015-12-06 17:01:03
【问题描述】:

我调用了一些返回 CFArrayCFStringRef 值的函数。我需要从他们那里得到 utf 字符串。由于我不想让我的代码过于复杂,所以我做了以下操作:

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

然后我将生成的字符串除以\ns 以获得一个 Swift 字符串数组。但是,当函数开始返回非 ascii 字符串时,麻烦就来了。我开始得到像“\U2345\U2344”这样的字符串。

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

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

值始终为空。

我怎样才能得到实际值?

【问题讨论】:

    标签: string swift utf-8


    【解决方案1】:

    这里有一些问题。首先,TISCreateInputSourceList() 名称中有“Create”,这意味着它返回一个 (+1) 保留 对象,您必须使用takeRetainedValue() 获取值, 不要takeUnretainedValue(),否则代码会泄漏内存:

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

    您现在可以使用CFArray... 方法从数组中获取值, 但将其转换为NSArray(即“免费桥接”)要容易得多:

    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)
    

    这会返回一个“空指针”(UnsafeMutablePointer&lt;Void&gt;),它必须被转换为一个对象 适当类型的指针(CFStringRef kTISPropertyInputSourceID 财产)。不幸的是,这有点 复杂(比较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)
    }
    

    【讨论】:

    • @Noobie: 否。let srcs = TISCreate....takeRetainedValue()“转让所有权”,当srcs超出范围时数组将被释放(因为Swift使用ARC)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 2012-02-09
    • 2021-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多