0

I'm trying to extract data out of a Dictionary<String, Any> in Swift. The dictionary returns the following when I run NSLog("\(terminalDict)"):

Optional(["DFEE22": <323c3c>, "DFEE20": <3c>, "DFEE21": <0a>, "DFEE17": <07>, "DFEE1E": , "DF10": <656e6672 65737a68>, "9F1C": <38373635 34333231>, "DFEE16": <00>, "DFEE15": <01>, "5F36": <02>, "DF11": <00>, "DFEE1F": <80>, "DFEE18": <80>, "9F1A": <0840>, "9F35": <21>, "9F4E": <31303732 31205761 6c6b6572 2053742e 20437970 72657373 2c204341 202c5553 412e>, "DF27": <00>, "DFEE1B": <30303031 35313030>, "DF26": <01>, "9F15": <1234>, "9F40": <f000f0a0 01>, "9F16": <30303030 30303030 30303030 303030>, "9F33": <6028c8>, "9F1E": <5465726d 696e616c>])

I want to get all the keys and values out of the dictionary and into one string variable (newSettings). This is how I was attempting to do that:

for (key, value) in terminalDict! {
    NSLog("key is now= \(key)")
    NSLog("value is now= \(value)")
    let asString = value as! String
    print(asString)
    NSLog("Adding \(key) \(asString)")
    newSettings = "\(newSettings)\(key)\(asString)"
  }

which returns:

key is now= DFEE22
value is now= {length = 3, bytes = 0x323c3c}
Could not cast value of type 'NSConcreteMutableData' (0x204aff148) to 'NSString' (0x204afde30).

How can I get the "323c3c" out of the dictionary as a simple string without the length and bytes portion? I can't find much documentation on type 'NSConcreteMutableData'. Do I have to use substring functions in order to get rid of the "length=x bytes=" part? I'm guessing there's a better way to do this than manually getting the substrings. Thanks.

  • 1
    Your dictionary is of type `[String:Data]`. And there are some values which cannot be represented by a string unless you prefer a hex string. – vadian Jul 26 '21 at 19:42
  • 1
    `NSConcreteMutableData`, that's a `Data`. Long story, it's in fact a `NSMutableData`, with a hidden implementation of Apple for optimization. But clearly, treat it as a `Data` instance. If you it as a hex string, see https://stackoverflow.com/questions/39075043/how-to-convert-data-to-hex-string-in-swift – Larme Jul 26 '21 at 19:45

1 Answers1

1

As Vadian says, your dictionaries contain Data values.

It looks like it is ASCII encoded text, but it's a bit hard to be sure.

This bit:

31303732 31205761 6c6b6572 2053742e 20437970 72657373 2c204341 202c5553 412e

Represents the string "10721 Walker St. Cypress, CA ,USA." when you treat it as ASCII.

you could use code like this:

for (key, value) in terminalDict! {
    NSLog("key is now= \(key)")

    // Decode the data into a String assuming it's ASCII
    let asString = String(data: value, encoding: .ascii)

    NSLog("value is now= '\(asString)'")
    print(asString)
    NSLog("Adding \(key) \(asString)")
    newSettings = "\(newSettings)\(key)\(asString)"
  }
Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Yes. This is very helpful. Another question: If I wanted to get the data that was in there as is(hex), without converting to ascii string, how would I do that? Is there a native way of doing that? @Larme suggested adding extension code, is there a native way of doing that? Thank, Duncan. – Gary Salgado Jul 27 '21 at 15:14
  • This thread includes an extension on Data that will convert Data to a string of hex values: https://stackoverflow.com/a/40089462/205185. You should be able to adapt that. – Duncan C Jul 27 '21 at 17:55
  • It's "sort of native" in that it uses `String(format:) with a format string of "%02hhX". – Duncan C Jul 27 '21 at 17:57
  • Note that it will generate a huge stream of hex digits. You might want to create a function that outputs hex values in clusters of 4 or 8 digits with spaces between, and newlines, so that it's easier to read. – Duncan C Jul 27 '21 at 17:58