21

I want to convert [String] to NSData for BLE Connection.

I know how to convert String to NSData / NSData to String.

// String -> NSData
var str: String = "Apple";
let data: NSData = str.dataUsingEncoding(NSUTF8StringEncoding)!

// NSData -> String
var outStr: String = NSString(data:data, encoding:NSUTF8StringEncoding) as! String

However, how can I convert,,

// [String] -> NSData ???
let strs: [String] = ["Apple", "Orange"]

This is a sample of converting [UInt8] <--> NSData https://gist.github.com/nolili/2bf1a701df1015ed6488

I want to convert [String] <--> NSData

// [String] -> NSData ??? Is it correct???
var strs: [String] = ["Apple", "Orange"]
let data2 = NSData(bytes: &strs, length: strs.count)

// NSData -> [String] ... please teach me..

3 Answers 3

25

Swift 4.2

[String] -> JSON -> Data

func stringArrayToData(stringArray: [String]) -> Data? {
  return try? JSONSerialization.data(withJSONObject: stringArray, options: [])
}

Data -> JSON -> [String]

func dataToStringArray(data: Data) -> [String]? {
  return (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String]
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is perfect answer!
13

For a direct answer to your question, you could ask each string in your array for its thisString.dataUsingEncoding(_:) and append the result to an NSMutableData instance until you're all done.

let stringsData = NSMutableData()
for string in strings {

    if let stringData = string.dataUsingEncoding(NSUTF16StringEncoding) {

        stringsData.appendData(stringData)

    } else {

        NSLog("Uh oh, trouble!")

    }

}

Of course this doesn't help you if you want to separate the strings later, so what we really need to know is how / in what environment do you intend to consume this data on the other end of your connection? If the other end uses Cocoa as well, consider just packaging it as a PLIST. Since NSString, NSArray, and NSData are all property list types, you can just archive your NSArray of NSString instances directly:

let arrayAsPLISTData = NSKeyedArchiver.archivedDataWithRootObject(strings)

...then transfer the resulting NSData instance to the Cocoa-aware destination and then:

if let newStrings: [String] = NSKeyedUnarchiver.unarchiveObjectWithData(arrayAsPLISTData) as? [String] {

    // ... do something

}

4 Comments

Thank you for your reply and sorry my late reply... I want to sent the [String] to other device via BLE connection. When we sent something via BLE, We use "writeValue" method. peripherl.writeValue(data: NSData, forCharacteristic: characteristic, type: responce type).
I used NSKeyedUnarchiver, it works!! Thank you very much. however, I dont know it's best way to convert NSData when sending msg via BLE Connection.
That still doesn't answer my question. What exactly is the BLE device doing with this data? What programming environment / language / device are you using these strings-as-data with? This is vitalninformation we need to know to even determine how to answer your question in a way you can use.
Thank you for your comment. programming environment is XCode 7.0, language is swift 2.0. I want to send a messages from iPhone A to iPhone B. iPhone A sends messages: [Stirng] after converting NSData with the function writeValue(data: NSData, forCharacteristic: characteristic, type: response type) . Then, iPhone B receives NSData from the func peripheralManager(peripheral: CBPeripheralManager, didReceiveWriteRequests requests: [CBATTRequest]) , convert requests[n] from NSData to [String] and updates message aria.
5

I tested this in iOS 9

func test() {
    let originalStrings = ["Apple", "Pear", "Orange"]
    NSLog("Original Strings: \(originalStrings)")

    let encodedStrings = stringArrayToNSData(originalStrings)
    let decodedStrings = nsDataToStringArray(encodedStrings)
    NSLog("Decoded Strings: \(decodedStrings)")
}

func stringArrayToNSData(array: [String]) -> NSData {
    let data = NSMutableData()
    let terminator = [0]
    for string in array {
        if let encodedString = string.dataUsingEncoding(NSUTF8StringEncoding) {
            data.appendData(encodedString)
            data.appendBytes(terminator, length: 1)
        }
        else {
            NSLog("Cannot encode string \"\(string)\"")
        }
    }
    return data
}

func nsDataToStringArray(data: NSData) -> [String] {
    var decodedStrings = [String]()

    var stringTerminatorPositions = [Int]()

    var currentPosition = 0
    data.enumerateByteRangesUsingBlock() {
        buffer, range, stop in

        let bytes = UnsafePointer<UInt8>(buffer)
        for var i = 0; i < range.length; ++i {
            if bytes[i] == 0 {
                stringTerminatorPositions.append(currentPosition)
            }
            ++currentPosition
        }
    }

    var stringStartPosition = 0
    for stringTerminatorPosition in stringTerminatorPositions {
        let encodedString = data.subdataWithRange(NSMakeRange(stringStartPosition, stringTerminatorPosition - stringStartPosition))
        let decodedString =  NSString(data: encodedString, encoding: NSUTF8StringEncoding) as! String
        decodedStrings.append(decodedString)
        stringStartPosition = stringTerminatorPosition + 1
    }

    return decodedStrings
}

2 Comments

thank you Robert and sorry my late reply. your code also worked at my env. thank you very much.
You are welcome, @ketancho, Good enough to mark it as the answer? (It would be my first :-))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.