Преобразование CFString в NSString - Swift
Я пытаюсь написать программу, которая будет проверять доступные последовательные порты и представлять их во всплывающем меню. Почему я не могу взять 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
}
}
}
Ответы
Ответ 1
Swift.String и NSString являются бесплатными мостами.
NSString и CFString могут быть переброшены друг к другу, но вы не можете напрямую переводить из строки Swift в CFString или наоборот.
Следуйте этим шагам, чтобы передать из строки Core Foundation в строку Swift:
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
Ответ 2
По крайней мере, с 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)
A более подробный пример:
// 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