2017-03-03 2 views
2

Je veux convertir un Int32 à une chaîne composée de quatre style C, 1 octet caractères larges (probablement étroitement lié à this mais Swift 3).Swift 3 - Comment convertir la mémoire de Int32 en quatre caractères

L'utilisation de ceci est que de nombreuses fonctions API de Core Audio renvoient un OSStatus (en réalité un Int32), qui peut souvent être interprété comme une chaîne composée de quatre caractères de style C.

fun interpretAsString(possibleMsg: Int32) -> String { 
    // Blackbox 
} 
+0

Possible dupliquer de [Comment convertir rapidement Int16 en deux UInt8 octets] (http://stackoverflow.com/questions/32830866/how-in-swift-to-convert-int16-to-two-uint8-bytes – BallpointBen

+0

Avez-vous essayé 'NSFileTypeForHFSTypeCode'? Malgré son nom, il peut convertir n'importe quel code 4-char de 'OSType' à' String' –

+0

@CodeDifferent: Ce n'est pas disponible sur iOS. –

Répondre

1

Je ne testons pas ce code, mais essayez ceci:

func interpretAsString(possibleMsg: Int32) -> String { 
    var result = String() 
    result.append(Character(UnicodeScalar(UInt32(possibleMsg>>24))!)) 
    result.append(Character(UnicodeScalar(UInt32((possibleMsg>>16) & UInt32(0xFF)))!)) 
    result.append(Character(UnicodeScalar(UInt32((possibleMsg>>8) & UInt32(0xFF)))!)) 
    result.append(Character(UnicodeScalar(UInt32((possibleMsg) & UInt32(0xFF)))!)) 
    return result 
} 
2

En fait, un "code à quatre caractères" est habituellement un non signé valeur 32 bits:

public typealias FourCharCode = UInt32 
public typealias OSType = FourCharCode 

Les quatre octets (du MSB au LSB) définissent chacun un caractère. est ici d'un simple Swift 3 fonction pour convertir le nombre entier en une chaîne, inspirée par les divers C/Objective-C/Swift 1 + 2 solutions dans iOS/C: Convert "integer" into four character string:

func fourCCToString(_ value: FourCharCode) -> String { 
    let utf16 = [ 
     UInt16((value >> 24) & 0xFF), 
     UInt16((value >> 16) & 0xFF), 
     UInt16((value >> 8) & 0xFF), 
     UInt16((value & 0xFF)) ] 
    return String(utf16CodeUnits: utf16, count: 4) 
} 

Exemple:

print(fourCCToString(0x48454C4F)) // HELO 

J'ai choisi un tableau avec les points de code UTF-16 comme stockage intermédiaire car cela peut directement être utilisé pour créer une chaîne.

Si vous avez vraiment besoin pour un signé entier 32 bits alors vous pouvez appel

fourCCToString(FourCharCode(bitPattern: i32value) 

ou définir une fonction similaire en prenant un paramètre Int32.

Comme Tim Vermeulen a suggéré ci-dessous, le tableau UTF-16 peut également être créé avec map:

let utf16 = stride(from: 24, through: 0, by: -8).map { 
    UInt16((value >> $0) & 0xFF) 
} 

ou

let utf16 = [24, 16, 8, 0].map { UInt16((value >> $0) & 0xFF) } 

À moins que la fonction est la performance critique pour votre application, choix ce que vous vous sentez le plus familier (autrement mesurer et comparer).

+0

J'utilise habituellement 'UInt16 (UInt8.max)' au lieu du '0xFF' quelque peu magique, bien que je suppose que c'est une question d'expérience. Je recommanderais aussi d'utiliser 'map' pour créer le tableau' chars', cela vous aurait fait gagner du temps lors de votre dernière édition :) –

+0

@TimVermeulen: Merci pour les commentaires. Je l'ai écrit de cette façon parce qu'il est facile à comprendre, et parce que je * suppose * qu'il permet au compilateur d'optimiser le code mieux (pas de méthodes avec des rappels appelés). –

+0

Je pense que le compilateur sera capable d'optimiser la 'map', mais il faudrait regarder l'assemblage généré. Je suis moins confiant sur le 'stride', mais vous pouvez toujours le remplacer par' [24, 16, 8, 0] 'si cela s'avère être un problème. –