Convertir CFString a NSString-Swift
serial-port iokit (2)
Estoy intentando escribir un programa que buscará los puertos serie disponibles y los presentará en un menú emergente. ¿Por qué no puedo tomar el CFString
directamente de la función IORegistryEntryCreateCFProperty()
y agregarlo al menú mediante la interpolación de cadenas en la siguiente línea? Por alguna razón mi declaración de variable se cumple con el error:
"NSString no es un subtipo de 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
}
}
}
Swift.String y NSString están puenteados sin cargo.
NSString y CFString se pueden convertir entre sí, pero no se puede convertir directamente de una Cadena Swift a una CFString o viceversa.
Siga estos pasos para emitir desde una Cadena Core Foundation a una Cadena Swift:
var cfStr:CFString = "Soon, I''ll be a Swift String"
var nsTypeString = cfStr as NSString
var swiftString:String = nsTypeString
Ejemplo para CFTypeRef:
var cfStr:CFTypeRef = "Soon, I''ll be a Swift String"
var nsTypeString = cfStr as NSString
var swiftString:String = nsTypeString
Al menos a partir de Swift 2.0 (verifique desde una terminal con swift --version
), puede convertir un CFString
a un Swift String
nativo con un simple as String
.
Esto es suficiente, ya que el tipo String
de Swift se puede usar en cualquier lugar NSString
se espere NSString
.
Un ejemplo con una constante kUTType*
(las constantes kUTType*
están definidas por CoreServices y son CFString
s):
// Get UTF8 plain text from the pasteboard.
import AppKit
let str = NSPasteboard.generalPasteboard().stringForType(kUTTypeUTF8PlainText as String)
Un ejemplo más detallado :
// 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
Para probar con qué tipo estás tratando:
cfStr is CFString // true
swiftStr is String // true
Para obtener el tipo de cadena , use .dynamicType
; en un contexto de cadena, esto informa el nombre del tipo, pero tenga en cuenta que puede recuperar el nombre de una clase interna privada :
"cfStr is a /(cfStr.dynamicType) instance."
// -> "cfStr is a _NSContiguousString instance." !!
Aún así, puedes tratar esto como una CFString
, como lo demuestra la prueba anterior.
Use _stdlib_getDemangledTypeName()
para obtener el verdadero nombre de clase subyacente :
_stdlib_getDemangledTypeName(cfStr) // -> "ObjectC.CFString"
_stdlib_getDemangledTypeName(kUTTypeUTF8PlainText) // ditto