Implement custom ImagePickController in iOS 13 - ios

How can I achieve something like this?
Right now I am using the standard UIImagePickerController like below, but it is quite boring and not a great user-experience.
Standard View:
// MARK: ImagePickerController
extension MainViewController: ImagePickerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
// delegate function
func showImagePickerControllerActionSheet() {
// choose Alert Options
let photoLibraryActionn = UIAlertAction(title: "Aus Album wählen", style: .default) { (action) in
self.showImagePickerController(sourceType: .photoLibrary)
}
let cameraAction = UIAlertAction(title: "Foto aufnehmen", style: .default) { (action) in
self.showImagePickerController(sourceType: .camera)
}
let cancelAction = UIAlertAction(title: "Zurück", style: .cancel, handler: nil)
AlertService.showAlert(style: .actionSheet, title: "Wähle ein Bild aus", message: nil, actions: [photoLibraryActionn, cameraAction, cancelAction], completion: nil)
}
func showImagePickerController(sourceType: UIImagePickerController.SourceType) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.allowsEditing = true
imagePickerController.sourceType = sourceType
present(imagePickerController, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let editedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
makeWishView.wishImageView.image = editedImage
makeWishView.wishImageButton.titleLabel?.text = ""
} else if let originalImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
makeWishView.wishImageButton.titleLabel?.text = ""
makeWishView.wishImageView.image = originalImage
}
dismiss(animated: true, completion: nil)
}
}
I couldn't find anything on this, happy for every help!

Related

There are two functions for uploading pictures in ViewController

I upload the image when button 1 is clicked, but the second image also shows the image uploaded by button 1!
What should I do so that the image uploaded on button 1 is displayed on image 1, and the image on the boat on button 2 is displayed on image 2?
Here is my code, thanks for your help
#IBAction func imageSelect(sender: Any){
let actionSheetController = UIAlertController()
let cancelAction = UIAlertAction(title: "取消", style: UIAlertAction.Style.cancel) { (alertAction) -> Void in
print("Tap 取消 Button")
}
let takingPicturesAction = UIAlertAction(title: "拍照", style: UIAlertAction.Style.destructive) { (alertAction) -> Void in
self.getImageGo(type: 1)
}
let photoAlbumAction = UIAlertAction(title: "相册", style: UIAlertAction.Style.default) { (alertAction) -> Void in
self.getImageGo(type: 2)
}
actionSheetController.addAction(cancelAction)
actionSheetController.addAction(takingPicturesAction)
actionSheetController.addAction(photoAlbumAction)
actionSheetController.popoverPresentationController?.sourceView = sender as? UIView
//显示
self.present(actionSheetController, animated: true, completion: nil)
}
#IBAction func imageSelect2(sender: Any){
let actionSheetController = UIAlertController()
let cancelAction = UIAlertAction(title: "取消", style: UIAlertAction.Style.cancel) { (alertAction) -> Void in
print("Tap 取消 Button")
}
let takingPicturesAction = UIAlertAction(title: "拍照", style: UIAlertAction.Style.destructive) { (alertAction) -> Void in
self.getImageGo(type: 1)
}
let photoAlbumAction = UIAlertAction(title: "相册", style: UIAlertAction.Style.default) { (alertAction) -> Void in
self.getImageGo(type: 2)
}
actionSheetController.addAction(cancelAction)
actionSheetController.addAction(takingPicturesAction)
actionSheetController.addAction(photoAlbumAction)
//iPad设备浮动层设置锚点
actionSheetController.popoverPresentationController?.sourceView = sender as? UIView
//显示
self.present(actionSheetController, animated: true, completion: nil)
}
func getImageGo(type:Int){
takingPicture = UIImagePickerController.init()
if(type==1){
takingPicture.sourceType = .camera
//takingPicture.showsCameraControls = true
}else if(type==2){
takingPicture.sourceType = .photoLibrary
}
takingPicture.allowsEditing = true
takingPicture.delegate = self
present(takingPicture, animated: true, completion: nil)
}
I think the problem is here in the code, but I don't know how to modify it, thanks for your help
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
takingPicture.dismiss(animated: true, completion: nil)
if(takingPicture.allowsEditing == false){
//原图
ID1.image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
ID2.image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
}else{
//截图
ID1.image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage
ID2.image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage
}
}

How to set the image taken/picked to the uiimage?

I am successful at taking or picking a photo and uploading to Firebase Storage but I am not sure how to set that pic to the UIImage, see code:
UIImage that needs the photo to be set to:
#IBOutlet weak var myPhoto: UIImageView!
How to select or take a photo:
imagePicker.allowsEditing = true
let alertController = UIAlertController(title: "Add a Photo", message: "Choose From", preferredStyle: .actionSheet)
let cameraAction = UIAlertAction(title: "Camera", style: .default) { (action) in
self.imagePicker.sourceType = .camera
self.imagePicked = sender.tag // new
self.present(self.imagePicker, animated: true, completion: nil)
}
let photosLibraryAction = UIAlertAction(title: "Photos Library", style: .default) { (action) in
self.imagePicker.sourceType = .photoLibrary
self.imagePicked = sender.tag // new
self.present(self.imagePicker, animated: true, completion: nil)
}
let savedPhotosAction = UIAlertAction(title: "Saved Photos Album", style: .default) { (action) in
self.imagePicker.sourceType = .savedPhotosAlbum
self.imagePicked = sender.tag // new
self.present(self.imagePicker, animated: true, completion: nil)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
alertController.addAction(cameraAction)
alertController.addAction(photosLibraryAction)
alertController.addAction(savedPhotosAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
How do I set the photo I just selected or took to myPhoto?
You can get selected or captured image from
UIImagePickerControllerDelegate function. You must need to set
delegate of your UIImagePickerController(picker) instance.

 Asking for permission
The app must ask for permission from the user before accessing the
camera/ the saved photos.The app should display a message to the user
explaining why it needs the camera or photo library access. You can
set this message by setting the NSCameraUsageDescription and
NSPhotoLibraryUsageDescription key in the Info.plist file of your app.
This will work for the sure
imagePicker.delegate = self
extension StackOverflowViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController( picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var selectedImage: UIImage?
if let editedImage = info[.editedImage] as? UIImage {
selectedImage = editedImage
self.imgView.image = selectedImage!
} else if let originalImage = info[.originalImage] as? UIImage {
selectedImage = originalImage
self.imgView.image = selectedImage!
picker.dismiss(animated: true, completion: nil)
}
}
func imagePickerControllerDidCancel( picker: UIImagePickerController) {
picker.dismiss(animated: true) {
// Further logic to perform
}
}
}

 You can review all other related to UIImagePickerController from this
official reference link.
https://developer.apple.com/documentation/uikit/uiimagepickercontroller/infokey/1619164-originalimage

Swift 4 Image Picker Not Changing UIImageView

For some reason in my new project this code is not working which has worked for me before. The current code does not change the ui of profileImage.
Delegates
UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIGestureRecognizerDelegate
Code:
#IBOutlet weak var profileImage: UIImageView!
#IBAction func changeProfilePicture(_ sender: Any) {
print("Profile picture tapped")
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.allowsEditing = true
let alertController = UIAlertController(title: "Add Picture", message: "", preferredStyle: .actionSheet)
let photoLibraryAction = UIAlertAction(title: "Photo Library", style: .default) { (action) in
pickerController.sourceType = .photoLibrary
self.present(pickerController, animated: true, completion: nil)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
alertController.addAction(photoLibraryAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
#objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : Any]?) {
self.profileImage.image = image
self.dismiss(animated: true, completion: nil)
}
Console Output
errors encountered while discovering extensions: Error
Domain=PlugInKit Code=13 "query cancelled"
UserInfo={NSLocalizedDescription=query cancelled}
I have tried
#objc func
internal func
#objc internal func
self.profileImage.image = image does not set the UI and change the image
Correct delegate method
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[.originalImage] as? UIImage {
self.profileImage.image = image
}
else
if let image = info[.editedImage] as? UIImage {
self.profileImage.image = image
}
self.dismiss(animated: true, completion: nil)
}

Cropping an image with imagepickercontroller in swift

I am currently making a program in swift that involves a screen of choosing an image from either camera or photo library using action sheet. This is fully functional however I would like to be able to choose a square section from the selected image, similar to apple default apps. How can I implement this? Here is my functional code:
func chooseImage(_ sender: Any) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let actionSheet = UIAlertController(title: "Photo Source", message: "Choose a source", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (action:UIAlertAction) in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePickerController.sourceType = .camera
self.present(imagePickerController, animated: true, completion: nil)
}else{
print("Camera not available")
}
}))
actionSheet.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: { (action:UIAlertAction) in
imagePickerController.sourceType = .photoLibrary
self.present(imagePickerController, animated: true, completion: nil)
}))
actionSheet.addAction(UIAlertAction(title: "Default", style: .default, handler: { (action:UIAlertAction) in
self.avatarImageView.image = UIImage(named: "Avatar.png")
}))
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(actionSheet, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
avatarImageView.image = image
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
// Saves the User singleton object onto the device
static func saveData() {
let savedData = NSKeyedArchiver.archivedData(withRootObject: User.sharedUser)
UserDefaults.standard.set(savedData, forKey: "user")
}
You can use default controls to achieve image cropping.
self.imgPicker.allowsEditing = true
Delegate Method
//MARK: image picker delegate method
//MARK:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var image : UIImage!
if let img = info[UIImagePickerControllerEditedImage] as? UIImage
{
image = img
}
else if let img = info[UIImagePickerControllerOriginalImage] as? UIImage
{
image = img
}
picker.dismiss(animated: true,completion: nil)
}
Swift 4.0+
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var image : UIImage!
if let img = info[UIImagePickerController.InfoKey.editedImage] as? UIImage
{
image = img
}
else if let img = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
{
image = img
}
picker.dismiss(animated: true, completion: nil)
}
Don't forget to set allowsEditing to true.
Another option is to use TOCropViewController. Its does more with much less code. What I found good about it that it allows you to change the cropping rectangle.
class ViewController: UIViewController, CropViewControllerDelegate {
... //your viewcontroller code
func presentCropViewController {
let image: UIImage = ... //Load an image
let cropViewController = CropViewController(image: image)
cropViewController.delegate = self
present(cropViewController, animated: true, completion: nil)
}
func cropViewController(_ cropViewController: CropViewController,
didCropToImage image: UIImage, withRect cropRect: CGRect, angle: Int) {
// 'image' is the newly cropped version of the original image
}
}
Swift 5.0
The shortest way of declaring:
//MARK: image picker delegate method
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var image : UIImage!
if let img = info[.editedImage] as? UIImage {
image = img
} else if let img = info[.originalImage] as? UIImage {
image = img
}
picker.dismiss(animated: true,completion: nil)
}
Button sender:
#objc func buttonClicked(sender: UIButton!) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary) {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = UIImagePickerController.SourceType.photoLibrary
picker.allowsEditing = true
present(picker, animated: true, completion: nil)
}
}
Don't forget to grant Photo Library access in .plist
- (void)cropViewController:(TOCropViewController *)cropViewController didCropToImage:(UIImage *)image withRect:(CGRect)cropRect angle:(NSInteger)angle
{
[[NSUserDefaults standardUserDefaults] setObject:UIImageJPEGRepresentation(image, 1) forKey:#"image"];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"cameraOn"];
[cropViewController dismissViewControllerAnimated:YES completion:^{
[self performSegueWithIdentifier:#"YourSegueIdentifier" sender:self];
}];
//UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}
For (iOS13): Do all ViewController "cropController.modalPresentationStyle =.fullScreen" using storyboard or code.
This is work good and easily navigate to another controller. I also attached image so you can easily understand how to change presentation style.

How to make UIImagePickerController for camera and photo library at the same time in swift

I use UIImagePickerController to take a photo by camera of iPhone.
I want to show both "take a photo" and "choose a photo".
My code
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .camera
//imagePicker.sourceType = .PhotoLibrary
presentViewController(imagePicker, animated: true, completion: nil)
I tried to use imagePicker.sourceType = .Camera and imagePicker.sourceType = .PhotoLibrary together to do this, but it doesn't work...
Thank you
Import UIImagePickerControllerDelegate and create a variable to assign UIImagePickerController
var imagePicker = UIImagePickerController() and set imagePicker.delegate = self.
Create an action sheet to display options for 'Camera' and 'Photo library'.
On your button click action:
#IBAction func buttonOnClick(_ sender: UIButton)
{
self.btnEdit.setTitleColor(UIColor.white, for: .normal)
self.btnEdit.isUserInteractionEnabled = true
let alert = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: { _ in
self.openCamera()
}))
alert.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { _ in
self.openGallary()
}))
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
/*If you want work actionsheet on ipad
then you have to use popoverPresentationController to present the actionsheet,
otherwise app will crash on iPad */
switch UIDevice.current.userInterfaceIdiom {
case .pad:
alert.popoverPresentationController?.sourceView = sender
alert.popoverPresentationController?.sourceRect = sender.bounds
alert.popoverPresentationController?.permittedArrowDirections = .up
default:
break
}
self.present(alert, animated: true, completion: nil)
}
func openCamera()
{
if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerController.SourceType.camera))
{
imagePicker.sourceType = UIImagePickerController.SourceType.camera
imagePicker.allowsEditing = true
self.present(imagePicker, animated: true, completion: nil)
}
else
{
let alert = UIAlertController(title: "Warning", message: "You don't have camera", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
func openGallary()
{
imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
imagePicker.allowsEditing = true
self.present(imagePicker, animated: true, completion: nil)
}
Download sample project for Swift, SwiftUI
Swift 5 +:
Action sheet with camera and gallery:
//MARK:- Image Picker
#IBAction func imagePickerBtnAction(selectedButton: UIButton)
{
let alert = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: { _ in
self.openCamera()
}))
alert.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { _ in
self.openGallery()
}))
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
Camera image picker functionality:
func openCamera()
{
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerController.SourceType.camera
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
else
{
let alert = UIAlertController(title: "Warning", message: "You don't have camera", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
Gallery image picker functionality:
func openGallery()
{
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
self.present(imagePicker, animated: true, completion: nil)
}
else
{
let alert = UIAlertController(title: "Warning", message: "You don't have permission to access gallery.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
ImagePicker delegate:
//MARK:-- ImagePicker delegate
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let pickedImage = info[.originalImage] as? UIImage {
// imageViewPic.contentMode = .scaleToFill
}
picker.dismiss(animated: true, completion: nil)
}
set delegate like:
UIImagePickerControllerDelegate,UINavigationControllerDelegate
take one imageview so we can display selected/captured image:
#IBOutlet weak var imageViewPic: UIImageView!
For capture new image by using device camera:
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
For select photo from gallery:
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
self.present(imagePicker, animated: true, completion: nil)
}
This is the delegate method :
//MARK: - ImagePicker delegate
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
// imageViewPic.contentMode = .scaleToFill
imageViewPic.image = pickedImage
}
picker.dismiss(animated: true, completion: nil)
}
set permission for access camera and photo in info.plist like:
<key>NSCameraUsageDescription</key>
<string>This app will use camera</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>You can select photo</string>
100% working and tested
Create view controller and add button and image in the storyboard
add UIImagePickerControllerDelegate,UINavigationControllerDelegate protocols in view controller
camera action button enter following code
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let actionsheet = UIAlertController(title: "Photo Source", message: "Choose A Sourece", preferredStyle: .actionSheet)
actionsheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (action:UIAlertAction)in
if UIImagePickerController.isSourceTypeAvailable(.camera){
imagePickerController.sourceType = .camera
self.present(imagePickerController, animated: true, completion: nil)
}else
{
print("Camera is Not Available")
}
}))
actionsheet.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: { (action:UIAlertAction)in
imagePickerController.sourceType = .photoLibrary
self.present(imagePickerController, animated: true, completion: nil)
}))
actionsheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(actionsheet,animated: true, completion: nil)
Add following function in view controller
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
imageView.image = image
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}
in info.plist add row with
Privacy - Photo Library Usage Description
Privacy - Camera Usage Description
I created this beautiful project and with these four lines of code you get image either from camera or library and apply beautiful filters with a single line like this : -
let picker = PickerController()
picker.applyFilter = true // to apply filter after selecting the picture by default false
picker.selectImage(self){ image in
// Use the picture
}
Here's the link of the project.
//MARK:- Camera and Gallery
func showActionSheet(){
//Create the AlertController and add Its action like button in Actionsheet
let actionSheetController: UIAlertController = UIAlertController(title: NSLocalizedString("Upload Image", comment: ""), message: nil, preferredStyle: .actionSheet)
actionSheetController.view.tintColor = UIColor.black
let cancelActionButton: UIAlertAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { action -> Void in
print("Cancel")
}
actionSheetController.addAction(cancelActionButton)
let saveActionButton: UIAlertAction = UIAlertAction(title: NSLocalizedString("Take Photo", comment: ""), style: .default)
{ action -> Void in
self.camera()
}
actionSheetController.addAction(saveActionButton)
let deleteActionButton: UIAlertAction = UIAlertAction(title: NSLocalizedString("Choose From Gallery", comment: ""), style: .default)
{ action -> Void in
self.gallery()
}
actionSheetController.addAction(deleteActionButton)
self.present(actionSheetController, animated: true, completion: nil)
}
func camera()
{
let myPickerControllerCamera = UIImagePickerController()
myPickerControllerCamera.delegate = self
myPickerControllerCamera.sourceType = UIImagePickerController.SourceType.camera
myPickerControllerCamera.allowsEditing = true
self.present(myPickerControllerCamera, animated: true, completion: nil)
}
func gallery()
{
let myPickerControllerGallery = UIImagePickerController()
myPickerControllerGallery.delegate = self
myPickerControllerGallery.sourceType = UIImagePickerController.SourceType.photoLibrary
myPickerControllerGallery.allowsEditing = true
self.present(myPickerControllerGallery, animated: true, completion: nil)
}
//MARK:- *************** UIImagePickerController delegate Methods ****************
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
// The info dictionary may contain multiple representations of the image. You want to use the original.
guard let selectedImage = info[.originalImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
// Set photoImageView to display the selected image.
imageUserProfile.image = selectedImage
// Dismiss the picker.
dismiss(animated: true, completion: nil)
}
Swift 5 Easy way just call function
//MARK Life Cycles
override func viewDidLoad() {
super.viewDidLoad()
choosePicture
}
extension AddBook: UIPickerViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#objc func choosePicture(){
let alert = UIAlertController(title: "Select Image", message: "", preferredStyle: .actionSheet)
alert.modalPresentationStyle = .overCurrentContext
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (action) in
self.openCamera()
}))
alert.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: { (action) in
self.openGallary()
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
let popoverController = alert.popoverPresentationController
popoverController?.permittedArrowDirections = .up
self.present(alert, animated: true, completion: nil)
}
func openCamera() {
if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerController.SourceType.camera))
{
imagePicker.sourceType = UIImagePickerController.SourceType.camera
imagePicker.allowsEditing = true
self.present(imagePicker, animated: true, completion: nil)
}
else
{
let alert = UIAlertController(title: "Warning", message: "You don't have camera", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
func openGallary() {
imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
imagePicker.allowsEditing = true
self.present(imagePicker, animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// picker.supportedInterfaceOrientations = .
if let image = info[UIImagePickerController.InfoKey.originalImage.rawValue] as? UIImage {
if btnPicOther.tag == 1 {
btnPicOther.setImage(image, for: .normal)
}
else if btnPicBack.tag == 1 {
btnPicBack.setImage(image, for: .normal)
}
else if btnPicFront.tag == 1{
btnPicFront.setImage(image, for: .normal)
}
picker.dismiss(animated: true, completion: nil)
}
}
}
Swift 5: you may use the camera image below:
Create a project
In the main Storyboard, add two buttons in the bottom & add imageView & link to viewController.
Add Privacy - Camera Usage Description permission in Info.plist like below:
Paste below code in view controller:
class ViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func btnPhotGalary(_ sender: Any) {
let picker = UIImagePickerController()
picker.sourceType = .photoLibrary
picker.delegate = self
present(picker, animated: true)
}
#IBAction func btnCapture(_ sender: Any) {
let picker = UIImagePickerController()
picker.sourceType = .camera
//for camera front
// picker.cameraDevice = .front
picker.delegate = self
picker.allowsEditing = false
present(picker, animated: true)
}
}
extension ViewController :UIImagePickerControllerDelegate,UINavigationControllerDelegate{
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true, completion: nil)
guard let originalImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else {
return
}
//for image rotation
let image = originalImage.upOrientationImage()
imageView.image = image
}
}
extension UIImage {
func upOrientationImage() -> UIImage? {
switch imageOrientation {
case .up:
return self
default:
UIGraphicsBeginImageContextWithOptions(size, false, scale)
draw(in: CGRect(origin: .zero, size: size))
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result
}
}
}
Full source is given in GitHub: https://github.com/enamul95/UIImagePicker.git
This will create a reusable class that will show an action sheet when your image, button, etc. is tapped.
import Foundation
import UIKit
class CameraHandler: NSObject{
static let shared = CameraHandler()
fileprivate var currentVC: UIViewController!
//MARK: Internal Properties
var imagePickedBlock: ((UIImage) -> Void)?
func camera()
{
if UIImagePickerController.isSourceTypeAvailable(.camera){
let myPickerController = UIImagePickerController()
myPickerController.delegate = self
myPickerController.allowsEditing = true
myPickerController.sourceType = .camera
currentVC.present(myPickerController, animated: true, completion: nil)
}
}
func photoLibrary()
{
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary){
let myPickerController = UIImagePickerController()
myPickerController.delegate = self
myPickerController.allowsEditing = true
myPickerController.sourceType = .photoLibrary
currentVC.present(myPickerController, animated: true, completion: nil)
}
}
func showActionSheet(vc: UIViewController) {
currentVC = vc
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (alert:UIAlertAction!) -> Void in
self.camera()
}))
actionSheet.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { (alert:UIAlertAction!) -> Void in
self.photoLibrary()
}))
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
vc.present(actionSheet, animated: true, completion: nil)
}
}
extension CameraHandler: UIImagePickerControllerDelegate, UINavigationControllerDelegate{
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
// The info dictionary may contain multiple representations of the image. Since we said "allowsEditing = true" we need to set this to ".editedImage".
guard let selectedImage = info[.editedImage] as? UIImage else {
fatalError("“Expected a dictionary containing an image, but was provided the following: \(info)")
}
// Set photoImageView to display the selected image.
self.imagePickedBlock?(selectedImage)
// Dismiss the picker.
currentVC.dismiss(animated: true, completion: nil)
}
}
TO USE IT
Make sure you set your info PList like this image below.
Create a storyboard with an UIImageView and drag imageView to ViewController. This will create a #IBOutlet like you see in the code below. I named my imageView profileImageView.
create a UIImage and set it to an image in your asset folder or use a system image. If using a system image it should look like this UIImage(systemName: "plus") NOTE: plus is an example pass whatever system image you like there.
(4) Create a function that updates the profileImageView to meet your needs, add the image to the profileImageView and then call this function in ViewDidLoad()
(5) In the same function I setup a tapGestureRecognizer so anytime the imageView it tapped it is notified and fires the editImageTapGesture() func.
(6) Setup the editImageTapGesture func to access the CameraHandler and show action sheet as well as assign the image (you select from library or take from camera) to your profileImageView.
import UIKit
class EditProfileImageController: UIViewController {
// (2) IBOutlet from storyboard
#IBOutlet weak var profileImageView: UIImageView!
// (3) Add image: this can be a system image or in my case an image in my assets folder named "noImage".
var profileImage = UIImage(named: "noImage")
override func viewDidLoad() {
super.viewDidLoad()
setupProfileImage()
}
//(4) I setup the profile image in this function and set profile image to the profileImageView
private func setupProfileImage() {
profileImageView.contentMode = .scaleAspectFill
profileImageView.image = profileImage
//(5) setup tap gesture for when profileImageView is tapped
profileImageView.isUserInteractionEnabled = true
let editImageTapGesture = UITapGestureRecognizer(target: self, action: #selector(editProfileImageTapped(_:)))
profileImageView.addGestureRecognizer(editImageTapGesture)
}
//(6) Once tap on profile image occurs the action sheet appears with Gallery and Camera buttons.
#objc func editProfileImageTapped(_ sender: UITapGestureRecognizer) {
CameraHandler.shared.showActionSheet(vc: self)
CameraHandler.shared.imagePickedBlock = { (image) in
self.profileImageView.image = image
}
}
}
Action Sheet should look like this:

Resources