1

I've an [UInt8] array containing ASCII codes and I want to create a String from it passing from a NSMutableData

I use the method appendBytes and pass to it the swift array address and everything works fine

The problem is when I need to pass a different from zero index, the expression &arr[5] is obviously wrong

The example below shows how to create the string starting from zero and taking 5 characters (the string "hello").

How do I must modify the code to start from position 6 and get the string "world"?

    var arr = [UInt8](count:100, repeatedValue:0)
    arr[0] = 104 // h
    arr[1] = 101 // e
    arr[2] = 108 // l
    arr[3] = 108 // l
    arr[4] = 111 // o
    arr[5] = 32 // space
    arr[6] = 119 // w
    arr[7] = 111 // o
    arr[8] = 114 // r
    arr[9] = 108 // l
    arr[10] = 100 // d
    var data = NSMutableData()
    data.appendBytes(&arr, length: 5)
    let str = NSString(data: data, encoding: NSASCIIStringEncoding)
    println("string from index zero = \(str)")
dafi
  • 3,492
  • 2
  • 28
  • 51

2 Answers2

1

You can wrap byte array into NSData and access required bytes using subdataWithRange(...), here is the code:

let readOnlyData = NSData(bytesNoCopy: &arr, length: arr.count) // notice bytesNoCopy, working with the same bytes
let subRangeData = readOnlyData.subdataWithRange(NSMakeRange(6, 5))
let str = NSString(data: subRangeData, encoding: NSASCIIStringEncoding)
Keenle
  • 12,010
  • 3
  • 37
  • 46
  • This helps very much, maybe I can work directy with `NSData` and remove the `arr` just to mimimize the objects to allocate. It's really frustrating converting a simple pointer operation in many allocations... – dafi Jul 16 '14 at 04:42
  • NSData is a wrapper designed for efficient work with arrays(code wise). I suggest you to go with it. In addition NSData very well integrated with NSString and other classes. – Keenle Jul 16 '14 at 04:50
0

You can create a subarray and pass reference to it:

var subA = Array(arr[6...10])
data.appendBytes(&subA, length:subA.count)
Keenle
  • 12,010
  • 3
  • 37
  • 46
  • So addressing a simple pointer becomes a very inefficient code, my real code is inside a loop so creating dozen of subarrays is overkilling – dafi Jul 15 '14 at 15:42
  • Swift arrays are copied lazily -- I haven't checked, but constructing an `Array` from a `Slice` of another should get you the same bytes. (You could probably test this by writing an ObjC test case and passing it various Swift subarrays, then looking at the pointers your ObjC code receives.) – rickster Jul 15 '14 at 16:47
  • @rickster `Slice` is not an `Array`, I mean `appendBytes(...)` does not accept slice pointer, that is why I had to pass it into `Array(...)` constructor. With `var` in front of variable it should definitely eat additional memory due to copy of items. I have posted another answer that solves the problem using `NSData`, hope it can help. – Keenle Jul 15 '14 at 17:19