我正在尝试编写一个程序来扫描可用的串口并在弹出菜单中显示它们。为什么我不能从CFString
函数直接取IORegistryEntryCreateCFProperty()
并在下一行通过字符串插值将其添加到菜单中?出于某种原因,我的变量声明遇到错误:
“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
}
}
}
答案 0 :(得分:15)
Swift.String和NSString是免费桥接的。
NSString和CFString可以相互转换,但不能直接从Swift String转换为CFString,反之亦然。
按照以下步骤从Core Foundation String转换为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
答案 1 :(得分:12)
至少从Swift 2.0开始(从swift --version
的终端验证),您可以将CFString
转换为原生Swift String
使用简单的as String
。
这已经足够了,因为Swift的String
类型可以在预期NSString
的任何地方使用。
具有kUTType*
常量的示例(kUTType*
常量由CoreServices定义,并且是CFString
s):
// 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." !!
仍然可以将此视为CFString
,因为上面的is
测试显示了这一点。
使用_stdlib_getDemangledTypeName()
获取真正的基础类名称:
_stdlib_getDemangledTypeName(cfStr) // -> "ObjectC.CFString"
_stdlib_getDemangledTypeName(kUTTypeUTF8PlainText) // ditto
答案 2 :(得分:0)
至于我,我喜欢扩展并在以后使用它们。 阅读起来似乎很方便和清楚:
扩展名:
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
]