2015-11-19 24 views
5

Mi piacerebbe usare let rawDataFromArray = NSData(bytes: myArray, length: ???), ma non so come ottenere la lunghezza dei byte per il mio array. Ecco alcuni esempi di ciò che potrebbe essere il mio allineamento:Come ottenere la dimensione dei byte per la matrice arbitraria in Swift?

let arr1 = [1, 2, 3] 
let arr2 = [1.0, 23556789000.0] 
let arr3 = ["hello", "ok", ""] 

func arrayLength(myArray: Array) -> Int { 
    var bytes = 0 
    for object in myArray { 
     // not sure what to do here 
    } 
    return bytes 
} 

Non sono sicuro se andare attraverso ogni elemento della matrice (ed in caso di stringhe che attraversano ogni personaggio, dal momento che emoji potrebbe avere più byte che li rappresentano) è il modo corretto per farlo.

Come ottenere la dimensione dei byte per l'array?
Qualcuno potrebbe dirmi il modo corretto di farlo?
O forse è solo che non è una buona pratica convertire Array in NSData in Swift?

Ho anche visto Converting Swift Array to NSData for persistent storage e Converting array of bytes to NSData e Custom Array to NSData, ma non sono riuscito a capire come ottenere la dimensione dei byte per tale array arbitrario.

+2

Vedere http://stackoverflow.com/questions/25714086/swift-use-sizeof-with-int32-array per un esempio che può essere utilizzato per un array di numeri interi o float. Ma non si può semplicemente trattare un array di * stringhe * come NSData, perché la struttura 'String' (che ha una dimensione fissa) contiene dei puntatori opachi alla memorizzazione effettiva dei caratteri. –

+0

Grazie a @MartinR. Quindi sembra una cattiva idea convertire una serie di stringhe in NSData. Puoi spiegare un po 'di più cosa sono i puntatori opachi? – Andrej

+1

'struct String' ha membri che non fanno parte dell'API" visibile "(ma puoi vederli nel debugger). Alcuni di questi sono puntatori alla memoria effettiva utilizzata per la stringa. (Quindi, per esempio, le stringhe identiche possono * condividere * l'archiviazione.) - Il punto è che 'struct String' non è autonomo. Se lo impacchettate in NSData, lo trasferite altrove e lo decomprimete, conterrà dei puntatori non validi. - Certo che * puoi * creare NSData da una serie di stringhe, ma devi aggiungere ogni stringa (ad esempio come stringa UTF-8 con terminazione NUL) separatamente. –

risposta

5

sembra che ci sia un equivoco: Per ogni tipo T, tutte le istanze del T hanno la stessa dimensione che può essere calcolata come sizeof(T). Nel caso di array, ci può essere un imbottitura tra elementi dell'array, pertanto la dimensione totale necessario per arr1 è

arr1.count * strideof(Int) 

(Confronto esempio Swift: How to use sizeof? per le sottili differenze tra sizeof() e strideof()).

Pertanto una funzione generica per creare NSData da un array sarebbe

extension Array { 
    func asData() -> NSData { 
     return self.withUnsafeBufferPointer({ 
      NSData(bytes: $0.baseAddress, length: count * strideof(Element)) 
     }) 
    } 
} 

Uso withUnsafeBufferPointer() garantisce che l'array utilizza memorizzazione contiguo per i suoi elementi.

Nel caso di tipi "semplici" come Int e Float questo dà i risultati attesi:

let arr1 = [1, 2, 3] 
print(arr1.asData()) 
// <01000000 00000000 02000000 00000000 03000000 00000000> 

let arr2 = [1.0, 23556789000.0] 
print(arr2.asData()) 
// <00000000 0000f03f 0000204c 60f01542> 

Tuttavia, è inutile per un array di stringhe:

let arr3 = ["hello", "ok", ""] 
print(arr3.asData()) 
// <945b2900 01000000 05000000 00000000 00000000 00000000 9a5b2900 01000000 02000000 00000000 00000000 00000000 068d2900 01000000 02000000 00000080 00000000 00000000> 

perché struct String contiene puntatori (nascosti/non documentati) sull'effettiva memorizzazione dei caratteri .

Una possibilità sarebbe quella di aggiungere ogni stringa come UTF-8 stringa NUL-terminated:

let data3 = NSMutableData() 
arr3.forEach { string in 
    string.withCString { 
     data3.appendBytes($0, length: Int(strlen($0)) + 1) 
    } 
} 
print(data3) 
// <68656c6c 6f006f6b 00f09f91 8d00> 

alternativa, utilizzare NSKeyedArchiver come i fili che si è indicato.

Problemi correlati