Преобразование 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