Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get a byte array from base64 in swift 3?

I'm translating an Android application to iOS with swift 3. My problem is with the next block of Java code:

String b64 = "KJT-AAAhtAvQ";
byte[] bytesCodigo = Base64.decode(b64, Base64.URL_SAFE);
System.out.Println(bytesCodigo.length) // 9

How would it be in swift?

Thanks

like image 658
Careuno Merchan Avatar asked Dec 19 '22 09:12

Careuno Merchan


1 Answers

One would just create a Data (NSData in Objective-C) from the base64 string. Note, though, that the standard Data(base64Encoded:) does not have “URL Safe” rendition, but you can create one that replaces “-” with “+” and “_” with “/” before trying to convert it:

extension Data {
    init?(base64EncodedURLSafe string: String, options: Base64DecodingOptions = []) {
        let string = string
            .replacingOccurrences(of: "-", with: "+")
            .replacingOccurrences(of: "_", with: "/")

        self.init(base64Encoded: string, options: options)
    }
}

Then you can do:

guard let data = Data(base64EncodedURLSafe: string) else { 
    // handle errors in decoding base64 string here
    return 
}

// use `data` here

Obviously, if it was not a “URL safe” base64 string, you could simply do:

guard let data = Data(base64Encoded: string) else { 
    // handle errors in decoding base64 string here
    return 
}

// use `data` here

You asked how one gets a “byte array”: Data effectively is that, insofar as the Data type conforms to the RandomAccessCollection protocol, just as the Array type does. So, you have many of the “array” sort of behaviors should you need them, e.g.:

for byte in data {
    // do something with `byte`, a `UInt8` value
}

or

let hexString = data.map { String(format: "%02x", $0) }
    .joined(separator: " ")

print(hexString)                        // 28 94 fe 00 00 21 b4 0b d0

So, in essence, you generally do not need a “byte array” as Data provides all the sort of access to the bytes that you might need. Besides, most Swift APIs handling binary data expect Data types, anyway.


If you literally need an [UInt8] array, you can create one:

let bytes = data.map { $0 }

But it is generally inefficient to create a separate array of bytes (especially when the binary payload is large) when the Data provides all the array behaviors that one would generally need, and more.

like image 187
Rob Avatar answered Dec 29 '22 12:12

Rob