Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert CFString to NSString - Swift

Tags:

I'm trying to write a program that will scan for available serial ports and present them in a popup menu. Why can I not take the CFString straight from the IORegistryEntryCreateCFProperty() function and add it to the menu via string interpolation in the next line? For some reason my variable declaration is met with the error:

"NSString is not a subtype of 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         }      } } 
like image 531
user3185748 Avatar asked Aug 17 '14 17:08

user3185748


2 Answers

Swift.String and NSString are toll free bridged.

NSString and CFString can be cast to one another, but you can't directly cast from a Swift String to a CFString or vice versa.

Follow these steps to cast from a Core Foundation String to a Swift String:    

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

Example for CFTypeRef:

var cfStr:CFTypeRef = "Soon, I'll be a Swift String" var nsTypeString = cfStr as NSString var swiftString:String = nsTypeString 
like image 183
Woodstock Avatar answered Oct 05 '22 07:10

Woodstock


At least as of Swift 2.0 (verify from a terminal with swift --version), you can convert a CFString to a native Swift String with a simple as String.

This is sufficient, since Swift's String type can be used anywhere NSString is expected.

An example with a kUTType* constant (kUTType* constants are defined by CoreServices and are CFStrings):

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

A more detailed example:

// 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 

To test what type you're dealing with:

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

To get the string's type, use .dynamicType; in a string context, this reports the type name but note that you may get the name of a private internal class back:

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

Still, you can treat this as a CFString, as the is test above shows.

Use _stdlib_getDemangledTypeName() to get the true, underlying class name:

_stdlib_getDemangledTypeName(cfStr) // -> "ObjectC.CFString" _stdlib_getDemangledTypeName(kUTTypeUTF8PlainText) // ditto 
like image 29
mklement0 Avatar answered Oct 05 '22 08:10

mklement0