3

I have an image in the string (base 64) how I can decode this string for Image() using SwiftUI.

Know I am using this format:

Image(imageFromAppGroup(key: "image0")).resizable().frame(width: 70, height: 70)
                            .cornerRadius(10)
                            .background(Color(red: 0.218, green: 0.215, blue: 0.25))

I need a past base 64 images instead of "image0". How I can do this?

2 Answers 2

10

You can use a UIImage for this:

let str = "IMAGE"
Image(uiImage: UIImage(data: Data(base64Encoded: str)!)!)

You will not want to force unwrap with ! here, so you should handle that too:

let str = "IMAGE"

if let data = Data(base64Encoded: str), let uiImage = UIImage(data: data) {
    Image(uiImage: uiImage)
} else {
    let _ = print("FAIL")
}

You could also create an Image extension:

extension Image {
    init?(base64String: String) {
        guard let data = Data(base64Encoded: base64String) else { return nil }
        guard let uiImage = UIImage(data: data) else { return nil }
        self = Image(uiImage: uiImage)
    }
}

/* ... */

var body: some View {
    Image(base64String: str)
}
Sign up to request clarification or add additional context in comments.

2 Comments

According to stackoverflow.com/a/60732521/2926577 , UIImage should be avoided in SwiftUI because " it's like using objective c code in swift which doesn't make sense of releasing a new language". Is this accurate? If yes, is there a way to decode base64 into something that's acceptable by Image() omitting UIImage?
@user2926577 No, using UIImage is not bad at all if used correctly. In SwiftUI, the main thing is to not initialize a UIImage in a view init or body, especially the body. This is because if the init takes a while, the view is slow to be created. If the UIImage is created in the body, it will be recreated every time the view reloads which is expensive. Instead, create the image in onAppear, set it to a @State variable, then create the SwiftUI Image in the body.
3

Something like this:

extension Image {
  init?(base64String: String) {
    guard let data = Data(base64Encoded: base64String) else { return nil }
    #if os(macOS)
    guard let image = NSImage(data: data) else { return nil }
    self.init(nsImage: image)
    #elseif os(iOS)
    guard let image = UIImage(data: data) else { return nil }
    self.init(uiImage: image)
    #else
    return nil
    #endif
  }
}

Usage:

Image(base64String: base64string)

2 Comments

Good idea of supporting for macOS too, but I wouldn't create an init like that without an explicit label. base64String gives context, and also Image already has an Image(_:) init, so this could cause issues.
is the Data initializer the best way in terms of performance to render base64 images ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.