PhillyPhoto
PhillyPhoto

Reputation: 103

Converting NSData to NSString in Swift 3?

I have a function that returns certain system values. It worked fine in Swift 2.2, and I just upgraded to Xcode 8 and Swift 3, and now it's failing.

func ioPlatExpertDevString(_ property: String) -> String {
    // Start tapping in to the IO Service
    let ioPlatformExpertDevice:io_service_t? = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"))

    var sAnswer = "Not Found"
    let cfAnswer:AnyObject! = IORegistryEntryCreateCFProperty(ioPlatformExpertDevice!, "\(property)" as CFString!, kCFAllocatorDefault, 0).takeRetainedValue()
    if (cfAnswer != nil) {
        let nsAnswer = (cfAnswer as! NSString)
        sAnswer = nsAnswer.uppercased
    }

    // Close the IO Service
    IOObjectRelease(ioPlatformExpertDevice!)

    return sAnswer
}

Prior, I was using "CFData" instead of "AnyObject". It builds fine, but at runtime, I get the following error:

Could not cast value of type '__NSCFData' (0x7fff7b833ec0) to 'NSString' (0x7fff7ac32038).

Upvotes: 3

Views: 9550

Answers (3)

kakubei
kakubei

Reputation: 5400

For more recent versions of Swift:

String(decoding: data, as: UTF8.self)

Upvotes: 1

Leo Valentim
Leo Valentim

Reputation: 461

Replace

let nsAnswer = (cfAnswer as! NSString) 

To

let nsAnswer = NSString(data: cfAnswer as! Data, encoding: String.Encoding.utf8.rawValue)

Upvotes: 5

vadian
vadian

Reputation: 285069

Please do not annotate types unless the compiler tell you to do.

For example IOServiceGetMatchingService returns a non-optional io_service_t, your optional annotation makes it worse.

IORegistryEntryCreateCFProperty returns Unmanaged<CFTypeRef>! an annotation is not needed either as well as the string interpolation and the cast to implicit unwrapped optional.

CFTypeRef can be bridge casted to a native Swift type.

If the return type is (NS)Data it's most unlikely that it worked in prior versions.

This code considers String and Data if the latter can be converted to String.

func ioPlatExpertDevString(_ property: String) -> String {
  // Start tapping in to the IO Service
  let ioPlatformExpertDevice = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"))

  var sAnswer = "Not Found"
  let cfAnswer = IORegistryEntryCreateCFProperty(ioPlatformExpertDevice, property as CFString, kCFAllocatorDefault, 0).takeRetainedValue()
  if let cfData = cfAnswer as? Data, let answer = String(data:cfData, encoding:.utf8) {
    sAnswer = answer.uppercased()
  } else if let answer = cfAnswer as? String {
    sAnswer = answer.uppercased()
  }
  // Close the IO Service
  IOObjectRelease(ioPlatformExpertDevice)
  return sAnswer
}

Upvotes: 0

Related Questions