将CFString转换为NSString - Swift

22
我正在尝试编写一个程序,它将扫描可用的串行端口,并在弹出菜单中呈现它们。为什么我不能直接从IORegistryEntryCreateCFProperty()函数中获取CFString并通过字符串插值将其添加到下一行中的菜单中?由于某种原因,我的变量声明遇到了错误:

"NSString不是CFString的子类型"。

import Foundation

import Cocoa

import IOKit
import IOKit.serial


@objc class Serial {

    init() {
    }

    @IBOutlet var serialListPullDown : NSPopUpButton!

    func refreshSerialList(defaultprompt: String) {


        let masterPort: mach_port_t = kIOMasterPortDefault
        let classesToMatch: CFDictionary =     IOServiceMatching(kIOSerialBSDServiceValue).takeUnretainedValue()
        var matchingServices: io_iterator_t = 0

        // remove everything from the pull down list
        serialListPullDown?.removeAllItems()

        // ask for all the serial ports
        let kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, &matchingServices)
        if kernResult == KERN_SUCCESS {
            // success
            while (io_object_t() == IOIteratorNext(matchingServices)) {
                var serialport = IORegistryEntryCreateCFProperty(io_object_t(), kIOCalloutDeviceKey, kCFAllocatorDefault, 0)

                serialListPullDown?.addItemWithTitle("\(serialport)")
            }
        }
        else {
            // error
        }

    }
}
3个回答

17

Swift.String 和 NSString 是免费桥接的。

NSString 和 CFString 可以互相转换,但是你不能直接将 Swift String 转换成 CFString 或者反过来。

按照以下步骤将 Core Foundation 字符串转换为 Swift String:

var cfStr:CFString = "Soon, I'll be a Swift String"
var nsTypeString = cfStr as NSString
var swiftString:String = nsTypeString

CFTypeRef的示例:

var cfStr:CFTypeRef = "Soon, I'll be a Swift String"
var nsTypeString = cfStr as NSString
var swiftString:String = nsTypeString

那么就变成这样了吗?http://imgur.com/ecm3JHM 因为对我来说它返回相同的错误。 - user3185748
@user3185748 CFTypeRef 就像 Core Foundation 中的 Any。 - Woodstock
首先,感谢您的耐心等待,让我试着理解这个问题。然而,建议使用的CFTypeRef似乎并没有解决这个问题:http://imgur.com/DxKrGiX - user3185748
也许Swift的最近更改改变了行为:至少在Swift 2.0版本中,您现在可以直接从CFString进行转换:var swiftString:String = cfStr as String。您的var swiftString:String = nsTypeString示例现在需要后缀as String才能编译。 - mklement0
如何在未桥接的系统上执行此操作(例如任何!APPLE系统)? - DrMickeyLauer
显示剩余6条评论

16

至少从Swift 2.0开始(可以通过终端使用swift --version进行验证),您可以使用简单的as StringCFString转换为本地的Swift String

这已经足够了,因为Swift的String类型可以在任何需要NSString的地方使用。

下面是一个kUTType*常量的示例kUTType*常量由CoreServices定义并且是CFString):

// Get UTF8 plain text from the pasteboard.
import AppKit
let str = NSPasteboard.generalPasteboard().stringForType(kUTTypeUTF8PlainText as String)

更详细的示例:

// Import at least the Foundation framework.
// Since Cocoa includes Foundation, `import Cocoa` works too.
// (Note that `import CoreServices`, even though it defines type `CFString`,
// is NOT enough - the conversion will fail.)
import Foundation

// Create a CFString.
// The fact that initializing from a `String` literal here works implies that
// the *reverse* cast - String -> CFString - also works.
var cfStr:CFString = "Cast me."

// Convert it to String.
var swiftStr = cfStr as String

测试你正在处理的对象的类型:


cfStr is CFString // true
swiftStr is String // true

要获取字符串的类型,请使用 .dynamicType;在字符串上下文中,这将报告类型名称,但请注意,您可能会获得一个私有内部类的名称:

"cfStr is a \(cfStr.dynamicType) instance."
// -> "cfStr is a _NSContiguousString instance." !!

不过,正如上面的is测试所示,您可以将此视为CFString处理。

使用_stdlib_getDemangledTypeName()函数获取真实的基础类名

_stdlib_getDemangledTypeName(cfStr) // -> "ObjectC.CFString"
_stdlib_getDemangledTypeName(kUTTypeUTF8PlainText) // ditto

2

就我而言,我喜欢制作扩展并在之后使用它们。

这似乎很方便且易于阅读:

扩展:

extension CFString {
    var string: String {
        return self as String
    }
}

使用方法:

let specificQueryPart: [String: NSObject] = [
            kSecReturnData.string: true as NSObject,
            kSecAttrService.string: key as NSObject,
            kSecMatchLimit.string: kSecMatchLimitOne
        ]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接