Working with bytes in Swift 4
Sometimes there is a need to implement an algorithm for encryption/decryption on strings, files or other data in your Swift project. Conversion for this type of algorithms from other languages (such as Java) to Swift, unfortunately is not straight forward.
Unicode Scalars
Behind the scenes, Swift’s native String
type is built from Unicode scalar values. A Unicode scalar is a unique 21-bit number for a character or modifier, such as U+0061
for LATIN SMALL LETTER A
("a"
) , or U+1F425
for FRONT-FACING BABY CHICK
("🐥"
)
In Swift a Character
can be constructed from a UnicodeScalar
value. And we can build a UnicodeScalar
from an Int
. This allows many conversions.
With utf8 and utf16, both properties on a String
, we can access all Int
values of the characters of a String
. With these properties, we can apply number-based conversions to characters.
Note:
Converting String
to byte array
and short array
let string: String = "abcd"let byteArray: [UInt8] = string.utf8.map{UInt8($0)}let shortArray: [UInt16] = string.utf16.map{UInt16($0)}// There is also another way with more encodingsif let data: Data = string.data(using: .windowsCP1252, allowLossyConversion: true) {// Now you can simply loop thru the bytes in datafor i in 0..<data.count {data[i] // UInt8 value}// Or if you still need it as UInt8 arraylet byteArrayFromData: [UInt8] = [UInt8](data)}
// Read more about data(using encoding: UInt, allowLossyConversion lossy: Bool) -> Data? from Apple doc:
https://developer.apple.com/documentation/foundation/nsstring/1413692-data
Converting byte array
and short array
to String
let byteArray: [UInt8] = [97, 98, 99, 100]let stringFromByteArray = String(data: Data(bytes: byteArray), encoding: .utf8)let shortArray: [UInt16] = [97, 98, 99, 100]let stringFromShortArray = shortArray.reduce("", {$0 + String(UnicodeScalar($1)!)})
Converting Character
to byte
and short
let character: Character = "a"let byte: UInt8 = String(character).utf8.map{UInt8($0)}[0]let short: UInt16 = String(character).utf16.map{UInt16($0)}[0]
Converting byte
and short
to Character
let byte: UInt8 = 100let characterFromByte: Character = Character(UnicodeScalar(byte))let short: UInt16 = 100// UnicodeScalar init with parameter value of UInt16 is optional
let characterFromShort: Character = Character(UnicodeScalar(short)!)
Here is a Character
class extension for simplifying the byte
and short
conversion
Useful bit-wise operators
To check all the available operators visit apple’s documentation from the links provided below.
Before you dive into converting an algorithm to Swift, there is one more important thing that you will need to know, Swift uses Unsigned Integers.
Unsigned and Signed Integers
Swift’s UInt8 — The UInt8
data type is an 8-bit unsigned integer. It has a minimum value of 0 and a maximum value of 255 (inclusive)
Java’s byte — The byte
data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive)
The difference between Java’s short
and Swift’s UInt16
is similar to byte
and UInt8
from above, so we can use the next definition for reference.
Java was used as an example programming language to point out the difference. There are other languages that use signed integers for byte
and short
.
More information about unsigned and signed integers can be found here: https://www.tutorialspoint.com/unsigned-and-signed-binary-numbers