2

I want to decode my nsData to a String Array. I have this code right now:

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

            var stringTerminatorPositions = [Int]()

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

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

                    currentPosition += 1
                }
            }

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

            return decodedStrings
        }

But I get an error on this line: let bytes = UnsafePointer<UInt8>(buffer)

Cannot invoke initializer for type 'UnsafePointer' with an argument list of type '(UnsafeRawPointer)'

Do I need to convert the buffer to a UnsafePointer? If so, how can I do that?

1 Answer 1

2

buffer in the enumerateBytes() closure is a UnsafeRawPointer and you have to "rebind" it to an UInt8 pointer in Swift 3:

// let bytes = UnsafePointer<UInt8>(buffer)
let bytes = buffer.assumingMemoryBound(to: UInt8.self)

But why so complicated? You can achieve the same result with

func nsDataToStringArray(nsData: NSData) -> [String] {
    let data = nsData as Data
    return data.split(separator: 0).flatMap { String(bytes: $0, encoding: .utf8) }
}

How does this work?

  • Data is a Sequence of UInt8, therefore
  • split(separator: 0) can be called on it, returning an array of "data slices" (which are views into the source data, not copies).
  • Each "data slice" is again a Sequence of UInt8, from which a String can be created with String(bytes: $0, encoding: .utf8). This is a failable initializer (because the data may be invalid UTF-8).
  • flatMap { ... } returns an array with all non-nil results, i.e. an array with all strings which could be created from valid UTF-8 code sequences between zero bytes.
Sign up to request clarification or add additional context in comments.

3 Comments

In Swift 3 I'd prefer the signature func stringArray(from nsData: NSData) ;-)
@vadian: Indeed! Or func stringArray(from data: Data), if possible. – I kept the name so that OP can directly test it with his/her code.
We don't need to talk about misusing obsolete NS... Foundation classes in Swift 3...

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.