Reputation: 638
I'm using an image picker that allows the user to upload a profile picture. However I do not know how to save the image after its selected. This is the image picker code I'm using. Once saved I would also like to retrieve the image in another view and display it.
image!
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 150, height: 150)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
.onTapGesture { self.shouldPresentActionScheet = true }
.sheet(isPresented: $shouldPresentImagePicker) {
SUImagePickerView(sourceType: self.shouldPresentCamera ? .camera : .photoLibrary, image: self.$image, isPresented: self.$shouldPresentImagePicker)
}.actionSheet(isPresented: $shouldPresentActionScheet) { () -> ActionSheet in
ActionSheet(title: Text("Choose mode"), message: Text("Please choose your preferred mode to set your profile image"), buttons: [ActionSheet.Button.default(Text("Camera"), action: {
self.shouldPresentImagePicker = true
self.shouldPresentCamera = true
}), ActionSheet.Button.default(Text("Photo Library"), action: {
self.shouldPresentImagePicker = true
self.shouldPresentCamera = false
}), ActionSheet.Button.cancel()])
}
Upvotes: 0
Views: 1274
Reputation: 313
It's not a good practice to save Image to Core Data, as you you'll need to encode into data while saving and decoding from data while retrieving. Also, I've read there are performance issues. The best practice is to use local storage to save an image, and Core Data saves a path to the image in storage. It can be completed like this. It's a good practice to set a unique image name like UUID()
func saveToDocumentDirectory(imageId: String) {
if let image = takenImage, let data = image.jpegData(compressionQuality: 0.7) {
do {
let filename = getDocumentsDirectory().appendingPathComponent(imageId)
try data.write(to: filename, options: [[.atomicWrite, .completeFileProtection]])
} catch {
print("error saving data")
}
}
}
You can call this function when you create a Core Data object like
saveToDocumentDirectory(imageId: object.id.uuidString)
Image can be retrieved with this method:
func retrieveImage(with id: UUID) {
let dummyImage = Image(systemName: "person")
do {
let filename = getDocumentsDirectory().appendingPathComponent(id.uuidString)
let data = try Data(contentsOf: filename)
if let uiImage = UIImage(data: data) {
return Image(uiImage: uiImage)
}
} catch {
print("error loading data")
return dummyImage
}
return dummyImage
}
Try using this image picker
import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {
@Environment(\.presentationMode) var presentationMode
@Binding var takenPicture: UIImage?
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[.originalImage] as? UIImage {
parent.takenPicture = image
}
parent.presentationMode.wrappedValue.dismiss()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.sourceType = .camera
picker.allowsEditing = false
picker.cameraFlashMode = UIImagePickerController.CameraFlashMode.off
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
}
Upvotes: 2