Selecting only PNG and JPEG in Image picker - ios

I would like to limit the user to only pick a PNG or JPEG image from the photo library.
I'm using SwiftUI in my project, this is my UIViewControllerRepresentable
struct ImagePickerRaw: UIViewControllerRepresentable {
#Environment(\.presentationMode) private var presentationMode
var sourceType: UIImagePickerController.SourceType = .photoLibrary
#Binding var selectedImage: UIImage
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePickerRaw>) -> UIImagePickerController {
let imagePicker = UIImagePickerController()
imagePicker.allowsEditing = false
imagePicker.sourceType = sourceType
imagePicker.mediaTypes = [UTType.png.identifier, UTType.jpeg.identifier]
imagePicker.delegate = context.coordinator
return imagePicker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePickerRaw>) {
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var parent: ImagePickerRaw?
init(_ parent: ImagePickerRaw) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage,
let parent = parent {
parent.selectedImage = image
}
parent?.presentationMode.wrappedValue.dismiss()
parent = nil
}
}
}
This is how I am trying to limit the user's choice, but I get an error message saying:
ImagePickerDemo[411:12746] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'No available types for source 0
I have also looked at this answer but my app just crashes.
I have tried imagePicker.mediaTypes = [UTType.image.identifier] but that includes gifs.
Is there a way I can limit the user to pick images only (excluding gifs)?

Works as documented:
Check for available types per call (as below) and choose which are to be used
[UIImagePickerController availableMediaTypesForSourceType:
self.sourceType];
Probably you wanted UIDocumentPickerViewController.

Related

Automatically Take Picture UIImagePickerController not working in SwiftUI

I want to automatically take an image in my application when the camera is presented. I am using SwiftUI and UIImagePickerController for the camera application.
Here is my code for the ImagePicker:
import Foundation
import SwiftUI
import UIKit
import MobileCoreServices
class ImagePickerCoordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
...
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
print("This should print if this method is called but it doesn't print")
let uiImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
image = uiImage
isShown = false
picker.dismiss(animated: true)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
isShown = false
}
}
struct ImagePicker: UIViewControllerRepresentable {
#Binding var isShown: Bool
#Binding var image: UIImage?
#Binding var didTapCapture: Bool
#State var pic = true
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
if pic{
uiViewController.takePicture() // this doesn't work and no image is found in the "func imagePickerController()" method above
}
}
func makeCoordinator() -> ImagePickerCoordinator {
return ImagePickerCoordinator(isShown: $isShown, image: $image)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
picker.sourceType = .camera
picker.cameraCaptureMode = .photo
picker.allowsEditing = false
//picker.mediaTypes = [kUTTypeMovie as String]
picker.showsCameraControls = false
return picker
}
}
From some research I did myself, I think that I need to present the picker before I can take a picture, but I am not sure how to do that? Or I might be headed down the wrong track.
Any help will be appreciated.

How to unselect an image from Image Picker in SwiftUI

I am creating a message app with SwiftUI.
I have made an Image Picker to allow sending photos.
Here is the code of my Image Picker :
import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {
#Binding var image: UIImage?
#Binding var didSet: Bool
private let controller = UIImagePickerController()
var sourceType: UIImagePickerController.SourceType = .photoLibrary
func makeCoordinator() -> Coordinator {
return Coordinator(parent: self)
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let parent: ImagePicker
init(parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
parent.image = info[.originalImage] as? UIImage
parent.didSet = true
picker.dismiss(animated: true)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true)
}
}
func makeUIViewController(context: Context) -> some UIViewController {
controller.sourceType = sourceType
controller.allowsEditing = false
controller.delegate = context.coordinator
return controller
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
}
When a picture is selected, it is shown in a view, so that, the user can see it before sending it.
I would like to implement a button that would unselect the image shown, but I don't know how to do it. I would like to know if there is a way to unselect the image.
Do you have any ideas ?
Thank you.

Value of type 'ImagePicker' has no member 'contentMode'

I'm trying to use contentMode like listed below but I don't understand why I receive the following error:
Cannot infer contextual base in reference to member 'scaleAspectFit'
Value of type 'ImagePicker' has no member 'contentMode'
if let uiImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
parent.contentMode = .scaleAspectFit <--- Error
parent.image = uiImage
}
parent.presentationMode.wrappedValue.dismiss()
}
}
Any hints?
Thank you!
attached you find the full code:
struct ImagePicker: UIViewControllerRepresentable {
#Environment(\.presentationMode) var presentationMode
#Binding var image: UIImage?
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
picker.allowsEditing = true
// picker.mediaTypes = ["public.image"]
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {}
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
let parent: ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
if let uiImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
parent.image.contentMode = .scaleAspectFit
parent.image = uiImage
}
parent.presentationMode.wrappedValue.dismiss()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
}
Add contentMode property
struct ImagePicker: UIViewControllerRepresentable {
#Environment(\.presentationMode) var presentationMode
#Binding var image: UIImage?
#Binding var mode:UIView.ContentMode? // here
Then
parent.mode = .scaleAspectFit

SwiftUI UIImagePickerController adds Black Bars in Landscape

I have a SwiftUI app with SwiftUI App lifecycle where the user can take photos of items
and store those images in the app persistent store. With one exception, the app
performs as expected. Both iPhone and iPad are supported. The exception is with photos
taken on an iPad in landscape mode. Those photos have a black band at the top and bottom
of the photo. I think that Apple only supports the portrait type capture, which would
be fine if I could crop the image to remove those bands. I've seen some older posts with this same issue, but none of the suggestions seems to apply now. I have not found any way to
eliminate the blackened area. I think my capture code is pretty standard.
In this image the green is what I get. The red is what I want.
struct CaptureImageView: View {
#Binding var isShown: Bool
#Binding var newUIImage: UIImage?
func makeCoordinator() -> Coordinator {
return Coordinator(isShown: $isShown, image: $newUIImage)
}
}
extension CaptureImageView: UIViewControllerRepresentable {
func makeUIViewController(context: UIViewControllerRepresentableContext<CaptureImageView>) -> UIImagePickerController {
let vc = UIImagePickerController()
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {
vc.sourceType = .camera
vc.allowsEditing = true
vc.cameraCaptureMode = .photo
vc.delegate = context.coordinator
return vc
}
return UIImagePickerController()
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<CaptureImageView>) {
}
}//extension
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
#Binding var isCoordinatorShown: Bool
#Binding var imageInCoordinator: UIImage?
init(isShown: Binding<Bool>, image: Binding<UIImage?>) {
_isCoordinatorShown = isShown
_imageInCoordinator = image
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let unwrapImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage else { return }
imageInCoordinator = unwrapImage
isCoordinatorShown = false
}//image picker controller
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
isCoordinatorShown = false
}
}//class
Any guidance would be appreciated. Xcode 14.3, iOS 14.3

Editing Images With PHPickerViewController SwiftUI

I want my user to be able to edit his image right after he picks it with the new PHPickerViewController, I was able to do it with UIImagePickercontroller like so:
struct ImagePicker: UIViewControllerRepresentable {
#Environment(\.presentationMode) var presentationMode
#Binding var image: UIImage?
typealias UIViewControllerType = UIImagePickerController
var sourceType : UIImagePickerController.SourceType = .camera
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
let parent: ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
if let uiImage = info[.editedImage] as? UIImage {
parent.image = uiImage
} else {
print("no image!")
}
parent.presentationMode.wrappedValue.dismiss()
}
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.sourceType = sourceType
picker.allowsEditing = true
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
}
But, when updating to Xcode 12.0 I need to support the iOS 14.0 users by implanting the PHPickerViewController like so:
#available(iOS 14, *)
struct PHPicker : UIViewControllerRepresentable {
func makeCoordinator() -> Coordinator {
return PHPicker.Coordinator(parent1: self)
}
#Binding var image : UIImage?
#Binding var picker : Bool
func makeUIViewController(context: Context) -> PHPickerViewController {
var config = PHPickerConfiguration()
config.filter = .images
config.selectionLimit = 1
let picker = PHPickerViewController(configuration: config)
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiView: PHPickerViewController, context: Context) {
}
class Coordinator: NSObject, PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
for img in results {
if img.itemProvider.canLoadObject(ofClass: UIImage.self){
img.itemProvider.loadObject(ofClass: UIImage.self) { (image, err) in
guard let image = image as? UIImage else {return}
self.parent.image = image
self.parent.picker = false
}
} else {
print("error getting image")
}
}
}
var parent : PHPicker
init(parent1: PHPicker) {
parent = parent1
}
}
}
How to I enable the user to edit his image (cutting, changing size, and so on...)?

Resources