Here's the relevant code:
@State private var selectedItem: PhotosPickerItem?
@State private var selectedPhoto: Data?
@State private var isShowingPhotoSourceDialog = false
@State private var isShowingPhotoLibraryPicker = false
@State private var isShowingCameraCapture = false
@State private var isShowingCameraUnavailableAlert = false
// Photo Button
Button {
isShowingPhotoSourceDialog = true
} label: {
Label(
selectedPhoto == nil ? "Add Photo" : "Change Photo",
systemImage: "photo"
)
.foregroundColor(.white)
.padding()
}
.frame(maxWidth: .infinity)
.background(Color.accent)
.listRowInsets(EdgeInsets())
.confirmationDialog("Add Photo", isPresented: $isShowingPhotoSourceDialog, titleVisibility: .visible) {
Button("Take Photo", systemImage: "camera") {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
isShowingCameraCapture = true
} else {
isShowingCameraUnavailableAlert = true
}
}
Button("Choose from Library", systemImage: "photo.on.rectangle") {
isShowingPhotoLibraryPicker = true
}
Button("Cancel", role: .cancel) { }
}
.photosPicker(isPresented: $isShowingPhotoLibraryPicker, selection: $selectedItem, matching: .images)
.onChange(of: selectedItem) {
Task {
if let data = try? await selectedItem?.loadTransferable(type: Data.self),
let image = UIImage(data: data) {
selectedPhoto = image.jpegData(compressionQuality: 0.5)
}
}
}
.sheet(isPresented: $isShowingCameraCapture) {
CameraCaptureView { image in
selectedPhoto = image.jpegData(compressionQuality: 0.5)
}
}
.alert("Camera Unavailable", isPresented: $isShowingCameraUnavailableAlert) {
Button("OK", role: .cancel) { }
} message: {
Text("This device does not have an available camera.")
}