This lesson takes us through the somewhat convoluted method by which an app can select a photo from the user’s photo library or use the camera.
Apparently, this is long-winding and convoluted because it’s not yet something SwiftUI can do and so we use a lot of UIKit code.
This is the code of our ImagePicker
:
import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {
@Environment(\.presentationMode) var presentationMode
var selectedSource: UIImagePickerController.SourceType
@Binding var recipeImage: UIImage?
func makeUIViewController(context: Context) -> UIImagePickerController {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = context.coordinator
imagePickerController.sourceType = selectedSource
return imagePickerController
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
}
func makeCoordinator() -> Coordinator {
Coordinator(parent: self)
}
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
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.recipeImage = image
}
parent.presentationMode.wrappedValue.dismiss()
}
}
}
I honestly can’t summarise what this does too much right now, only that it needs to be done. I shall be printing it and adding it to my Lever Arch file for frequent referral and revision.
In order to use our ImagePicker
code, we need to add a few things to our view that calls up the code.
import SwiftUI
struct AddRecipeView: View {
...
@State private var isShowingImagePicker = false
@State private var selectedImageSource = UIImagePickerController.SourceType.photoLibrary
@State private var placeHolderImage = Image("noImageAvailable")
var body: some View {
...
ScrollView (showsIndicators: false) {
VStack {
placeHolderImage
.resizable()
.scaledToFit()
HStack {
Button("Photo Library") {
selectedImageSource = .photoLibrary
isShowingImagePicker = true
}
Text(" | ")
Button("Camera") {
selectedImageSource = .camera
isShowingImagePicker = true
}
}
.sheet(isPresented: $isShowingImagePicker, onDismiss: loadImage) {
ImagePicker(selectedSource: selectedImageSource, recipeImage: $recipeImage)
}
...
}
}
}
.padding(.horizontal)
}
func loadImage() {
if recipeImage != nil {
placeHolderImage = Image(uiImage: recipeImage!)
}
}
}
Well, it does work, although we do need to use an actual device in order to use the camera, but there’s also one addition to our Info.plist that we need:
Now, I’m going off to re-read all of this one…