Search code examples
iosswiftuiimagebase64nsdata

Encoding/Decoding base64 decodedData = nil


Yesterday I wrote a working code for this, but I erased it and when writing a new one something is really weird:

I encode it a picture this way:

let pictureData = UIImagePNGRepresentation(picture!)
let pictureToString64 = pictureData?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)

(I had JPEGRepresentation before, but it wasn't working, so I tried with JPEG) and I decode this way by getting pic 64 which I believe it has the correct value. It starts with iVBORw0KGgoAAAANSUhEUgAAAUAA(...)

 let decodedData = NSData(base64EncodedString: pic64, options:NSDataBase64DecodingOptions(rawValue: 0))
 let decodedImage = UIImage(data: decodedData!)
 let pictureDataLocal = UIImageJPEGRepresentation(decodedImage!, 100)
                defaults.setObject(pictureDataLocal, forKey: "profilePicture")

The problem is that decodedData is always nil. Why is this happening?


Solution

  • I think this has to do with NSDataBase64DecodingOptions.

    Using NSDataBase64DecodingOptions.IgnoreUnknownCharacters instead of NSDataBase64DecodingOptions(rawValue: 0), I was able to decode the Base64 encoded string back into NSData, and created a UIImage from that data:

    let picture = UIImage(named: "myImage")
    
    let pictureData = UIImagePNGRepresentation(picture!)
    
    let pictureToString64 = pictureData?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
    
    let decodedData = NSData(base64EncodedString: pictureToString64!, options:NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
    let decodedImage = UIImage(data: decodedData!)
    let pictureDataLocal = UIImageJPEGRepresentation(decodedImage!, 100)
    

    NSDataBase64DecodingOptions inherits from OptionSetType which is why you get the rawValue initializer. It is better to use the one of the set types, rather passing in a value. I saw in the header that NSDataBase64DecodingOptions was the only public var in the struct, so I tried it.

    @available(iOS 7.0, *)
    public struct NSDataBase64DecodingOptions : OptionSetType {
        public init(rawValue: UInt)
    
        // Use the following option to modify the decoding algorithm so that it ignores unknown non-Base64 bytes, including line ending characters.
        public static var IgnoreUnknownCharacters: NSDataBase64DecodingOptions { get }
    }