I want to make a button that when pressed will take a photo, after I take a photo I can directly convert the photo to base64 and will be used to post to the API
This is my code :)
import SwiftUI
import UIKit
struct ImagePicker: UIViewControllerRepresentable {
@Binding var selectedImage: UIImage
@Environment(\.presentationMode) private var presentationMode
var sourceType: UIImagePickerController.SourceType = .photoLibrary
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let imagePicker = UIImagePickerController()
imagePicker.allowsEditing = false
imagePicker.sourceType = sourceType
imagePicker.delegate = context.coordinator
return imagePicker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
//leave alone for right now
}
final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var parent: ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
parent.selectedImage = image
}
parent.presentationMode.wrappedValue.dismiss()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
}
class ImageConverter {
func base64ToImage(_ base64String: String) -> UIImage? {
guard let imageData = Data(base64Encoded: base64String) else { return nil }
return UIImage(data: imageData)
}
func imageToBase64(_ image: UIImage) -> String? {
return image.jpegData(compressionQuality: 1)?.base64EncodedString()
}
}
This is some of my view, I want when I press the button it will direct me to the camera and when I take a photo it will convert it to base64 and save it in a string.
import SwiftUI
struct ProfileView: View {
let imageManager = ImageConverter()
@State var changeProfileImage = false
@State var openCameraRoll = false
@State var imageSelected = UIImage()
var body: some View {
ZStack(alignment: .bottomTrailing) {
Button(action: {
changeProfileImage = true
openCameraRoll = true
}, label: {
if changeProfileImage {
Image(uiImage: imageSelected)
.profileImageMod()
} else {
Image("AddProfileImage")
.profileImageMod()
}
})
Image(systemName: "plus")
.frame(width: 30, height: 30)
.foregroundColor(.white)
.background(Color.gray)
.clipShape(Circle())
}.sheet(isPresented: $openCameraRoll) {
ImagePicker(selectedImage: $imageSelected, sourceType: .camera)
}.onAppear {
}
}
}
UPDATE this is my Imagepicker
import SwiftUI
import UIKit
struct ImagePicker: UIViewControllerRepresentable {
@Binding var selectedImage: UIImage
@Environment(\.presentationMode) private var presentationMode
var sourceType: UIImagePickerController.SourceType = .photoLibrary
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let imagePicker = UIImagePickerController()
imagePicker.allowsEditing = false
imagePicker.sourceType = sourceType
imagePicker.delegate = context.coordinator
return imagePicker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
//leave alone for right now
}
final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var parent: ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
parent.selectedImage = image
}
parent.presentationMode.wrappedValue.dismiss()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
}
class ImageConverter {
func base64ToImage(_ base64String: String) -> UIImage? {
guard let imageData = Data(base64Encoded: base64String) else { return nil }
return UIImage(data: imageData)
}
func imageToBase64(_ image: UIImage) -> String? {
return image.jpegData(compressionQuality: 1)?.base64EncodedString()
}
}
you could use something like this approach, using the .onDismiss()
to then convert your imageSelected
to base64 string using your ImageConverter
.
In ProfileView
,
.sheet(isPresented: $openCameraRoll, onDismiss: didDismiss) {
ImagePicker(selectedImage: $imageSelected, sourceType: .camera)
}
func didDismiss() {
let b64Str = imageManager.imageToBase64(imageSelected)
print("\n---> b64Str: \(b64Str?.count) \n")
}
Also remove the ZStack
, or replace it by a VStack
EDIT-1: here some example code that works for me:
struct ProfileView: View {
let imageManager = ImageConverter()
@State var changeProfileImage = false
@State var openCameraRoll = false
@State var imageSelected = UIImage()
var body: some View {
VStack {
Button(action: {
openCameraRoll = true
}, label: {
Image(systemName: "plus")
// .profileImageMod()
})
if changeProfileImage {
Image(uiImage: imageSelected)
.resizable() // <-- here
.frame(width: 222, height: 222)
.foregroundColor(.white)
.background(Color.gray)
.clipShape(Circle())
} else {
Image(systemName: "questionmark")
.frame(width: 222, height: 222)
.foregroundColor(.white)
.background(Color.gray)
.clipShape(Circle())
}
}
.sheet(isPresented: $openCameraRoll, onDismiss: didDismiss) {
ImagePicker(selectedImage: $imageSelected, sourceType: .camera)
}
}
func didDismiss() {
changeProfileImage = true
let b64Str = imageManager.imageToBase64(imageSelected)
print("\n---> b64Str: \(b64Str?.count) \n")
}
}