When I present my UIImagePickerController, nothing comes up - ios

What I'm trying to do is present an alert, where the user eaither presess get photo from camera, or photolibrary. However, when I press library, the UIImagePickerViewController doesn't present. I am adding UIAlert actions to the ALert, and the handler of which I am passing in is as a function which presents the ImagePicker controller. What am I doing wrong? I suspect it has to do with how I am presenting the ImagePickerViewController, but I'm not sure. I read the apple docs and they said that a popover is the only style to present it.
import UIKit
import Firebase
class SignupViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var ProfilePic: UIButton!
//When button is pressed, alert will pop up
#IBAction func bringUpAlert(_ sender: Any) {
let alert = UIAlertController(title: "Profile Photo", message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(action) -> Void in
func showCamera(){
let camera = UIImagePickerController()
UIImagePickerController.isSourceTypeAvailable(.camera)
camera.delegate = self
camera.sourceType = .camera
self.present(camera, animated: true, completion: nil)
}
}))
alert.addAction(UIAlertAction(title: "Library", style: .default, handler: {(action) -> Void in
func showLibrary(){
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
let library = UIImagePickerController()
library.delegate = self
library.sourceType = .photoLibrary
library.modalPresentationStyle = UIModalPresentationStyle.popover
self.present(library, animated: true, completion: nil)
}
func imagePickerController(_picker: UIImagePickerController, didFinishPickingMediaWithInfo: [String:Any]) {
let selectedImage = didFinishPickingMediaWithInfo[UIImagePickerControllerOriginalImage] as! UIImage
self.ProfilePic.setImage(selectedImage, for: .normal)
}
}
}))
self.present(alert, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
//Customizing Profile Pic View
ProfilePic.layer.cornerRadius = ProfilePic.frame.size.width / 2
ProfilePic.clipsToBounds = true
ProfilePic.layer.borderWidth = 3
ProfilePic.layer.borderColor = UIColor.gray.cgColor
}
}

The image picker is never shown. In the action alert, the function showCamera is never called.
The solution is to remove the function.
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(action) -> Void in
let camera = UIImagePickerController()
UIImagePickerController.isSourceTypeAvailable(.camera)
camera.delegate = self
camera.sourceType = .camera
self.present(camera, animated: true, completion: nil)
}))
Or, move the showCamera function declaration outside and call it from the alert action.
func showCamera(){
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let camera = UIImagePickerController()
camera.delegate = self
camera.sourceType = .camera
self.present(camera, animated: true, completion: nil)
}
}
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(action) -> Void in
showCamera()
}))
The same is needed of the embedded showLibrary function. And the image picker delegate method also needs to be moved to the top-level of the class.
Final class:
class SignupViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var ProfilePic: UIButton!
//When button is pressed, alert will pop up
#IBAction func bringUpAlert(_ sender: Any) {
let alert = UIAlertController(title: "Profile Photo", message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(action) -> Void in
self.showCamera()
}))
alert.addAction(UIAlertAction(title: "Library", style: .default, handler: {(action) -> Void in
self.showLibrary()
}))
self.present(alert, animated: true, completion: nil)
}
func showCamera(){
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let camera = UIImagePickerController()
camera.delegate = self
camera.sourceType = .camera
self.present(camera, animated: true, completion: nil)
}
}
func showLibrary(){
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
let library = UIImagePickerController()
library.delegate = self
library.sourceType = .photoLibrary
library.modalPresentationStyle = UIModalPresentationStyle.popover
self.present(library, animated: true, completion: nil)
}
}
func imagePickerController(_picker: UIImagePickerController, didFinishPickingMediaWithInfo: [String:Any]) {
let selectedImage = didFinishPickingMediaWithInfo[UIImagePickerControllerOriginalImage] as! UIImage
self.ProfilePic.setImage(selectedImage, for: .normal)
}
override func viewDidLoad() {
super.viewDidLoad()
//Customizing Profile Pic View
ProfilePic.layer.cornerRadius = ProfilePic.frame.size.width / 2
ProfilePic.clipsToBounds = true
ProfilePic.layer.borderWidth = 3
ProfilePic.layer.borderColor = UIColor.gray.cgColor
}
}

Example 1:
func doStuff(x: Int, handler: (Int) -> Void) {
handler(x)
}
doStuff(x: 3) {val in
print(val)
}
--output:--
3
Example 2:
func doStuff(x: Int, handler: (Int) -> Void) {
handler(x)
}
doStuff(x: 3) {val in
func calc(a: Int, b: Int) {
print(a + b)
}
}
--output:--
<Nothing>
iOS programming isn't really for beginning programmers--it's hard for experienced programmers.

Related

alert view to pick camera or gallery doesn't pop up in swift 4

I have a viewcontroller with navigation controller. I have button for uploading images.But after pressing the button it doesn't popup the alert for camera or photo library options although i have written codes for alert. Why doesn't the alert popup appear? I have also given Privacy - Photo Library Usage Description in info.plist. My code is given :
import UIKit
import Alamofire
class ProfilePicController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var imagePicker = UIImagePickerController()
#IBOutlet weak var uploadPic: UIButton!
#IBOutlet weak var profilePic: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imagePicker.delegate = self
profilePic.layer.cornerRadius = profilePic.frame.size.width / 2
profilePic.clipsToBounds = true
// Do any additional setup after loading the view.
}
#IBAction func uploadPic(_ sender: Any) {
print("image add")
let alert = UIAlertController(title: nil, message: "Choose your source", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Camera", style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
print("Camera selected")
self.imagePicker.sourceType = UIImagePickerControllerSourceType.camera
})
alert.addAction(UIAlertAction(title: "Photo library", style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
print("Photo selected")
self.imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
})
self.present(self.imagePicker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
profilePic.image = selectedImage
// self.savePic()
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
//Alert.swift file
import UIKit
class Alert {
class func showBasic(title: String ,message: String , vc: UIViewController) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alert.addAction(defaultAction)
vc.present(alert, animated: true, completion: nil)
}
}
Actually you don't present the alert
#IBAction func uploadPic(_ sender: Any) {
print("image add")
let alert = UIAlertController(title: nil, message: "Choose your source", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Camera", style: .default) { (result : UIAlertAction) -> Void in
print("Camera selected")
self.imagePicker.sourceType = .camera
self.present(self.imagePicker, animated: true, completion: nil)
})
alert.addAction(UIAlertAction(title: "Photo library", style: .default) { (result : UIAlertAction) -> Void in
print("Photo selected")
self.imagePicker.sourceType = .photoLibrary
self.present(self.imagePicker, animated: true, completion: nil)
})
self.present(alert, animated: true, completion: nil)
}

Hiding Navigation Button

I have a simple app that allows the user to select an image from their device via Camera Roll or to take a new image. Easy.
I have two buttons;
1) on the navigation bar named Set Image which saves the image to core data
2) on the main view that opens the image picker controller.
My issue;
How do I hide the button on the navigation bar if an image has not been selected?
import UIKit
class CameraRollViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.setBackgroundImage(UIImage(),for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
}
#IBAction func addImage(_ sender: Any) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let actionSheet = UIAlertController(title: "Lets customize your Reminders Page", 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: "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
imageView.image = image
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}
Anyone have any idea how to do this?

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:

How to get the image picker in (swift 3) to switch back and 4th between photo gallery and camera.

This code allows access to my photo gallery on the iPhone simulator in Xcode. When I put it on my iPad I can access the camera but not the photo gallery. I would like the image view to display the camera photos if choose or load a image from the photo gallery if choose.
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let picker = UIImagePickerController()
#IBOutlet weak var iv: UIImageView!
#IBAction func cameraf(_ sender: UIBarButtonItem) {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
picker.allowsEditing = false
picker.sourceType = UIImagePickerControllerSourceType.camera
picker.cameraCaptureMode = .photo
picker.modalPresentationStyle = .fullScreen
present(picker,animated: true,completion: nil)
} else {
noCamera()
}}
#IBAction func photolibaryss(_ sender: UIBarButtonItem) {
picker.allowsEditing = false
picker.sourceType = .photoLibrary
picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
picker.modalPresentationStyle = .popover
present(picker, animated: true, completion: nil)
picker.popoverPresentationController?.barButtonItem = sender
}
func noCamera(){
let alertVC = UIAlertController(
title: "No Camera",
message: "Sorry, this device has no camera",
preferredStyle: .alert)
let okAction = UIAlertAction(
title: "OK",
style:.default,
handler: nil)
alertVC.addAction(okAction)
present(
alertVC,
animated: true,
completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
var chosenImage = UIImage()
chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
iv.contentMode = .scaleAspectFit
iv.image = chosenImage
dismiss(animated:true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}}
Update to the answer above. It works great, but has a few typos - need closing parentheses on addActions. Xcode 8.2 also changed presentViewController to present.
let alert = UIAlertController(title: nil, message: "Choose your source", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Camera", style: UIAlertActionStyle.Default) { (result : UIAlertAction) -> Void in
print("Camera selected")
//Code for Camera
//cameraf
})
alert.addAction(UIAlertAction(title: "Photo library", style: UIAlertActionStyle.Default) { (result : UIAlertAction) -> Void in
print("Photo selected")
//Code for Photo library
//photolibaryss
})
self.present(alert, animated: true, completion: nil)
You can make a UIAlertController which would consist of two alert actions photo library and camera, and then add the functions lines of code from photolibaryss and cameraf to respective alert actions.
let alert = UIAlertController(title: nil, message: "Choose your source", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Camera", style: UIAlertActionStyle.Default) { (result : UIAlertAction) -> Void in
print("Camera selected")
//Code for Camera
//cameraf
})
alert.addAction(UIAlertAction(title: "Photo library", style: UIAlertActionStyle.Default) { (result : UIAlertAction) -> Void in
print("Photo selected")
//Code for Photo library
//photolibaryss
})
self.present(alert, animated: true, completion: nil)

I want to let users choose either taking a photo using camera or picking a photo from library(ios-swift, apple example- foodtracker)

I'm playing with ios swift foodtracker example.
The default final example only let users choose a photo from a library.
But I want them to take a photo using camera.
So I tried the below code, but it didn't change the functionality. It still did went to the photo library without asking the user's option preference (camera/photolibrary).
I am getting the following error message:
Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior ()
And this is the code I used:
#IBAction func selectImageFromPhotoLibrary(sender: AnyObject) {
// Hide the keyboard.
nameTextField.resignFirstResponder()
// UIImagePickerController is a view controller that lets a user pick media from their photo library.
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: .Default, handler: {
action in
imagePickerController.sourceType = .Camera
self.presentViewController(imagePickerController, animated: true, completion: nil)
}))
alert.addAction(UIAlertAction(title: "Photo Library", style: .Default, handler: {
action in
imagePickerController.sourceType = .PhotoLibrary
self.presentViewController(imagePickerController, animated: true, completion: nil)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))
presentViewController(imagePickerController, animated: true, completion: nil)
}
Make sure you are using Navigation Controller, if not just embed it by going to your storyBoard --> Select your initial ViewController then Editor ->Embeded In -> Navigation Controller
To use imagePicker , use This : -
class ViewController : UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate{
.....
.....
.....
var imagePicker : UIImagePickerController!
//Defined it globally in the class
..
..
override func viewDidLoad() {
super.viewDidLoad()
imagePicker = UIImagePickerController()
self.imagePicker.delegate = self
//Initialise it in viewDidLoad
...
}
//In your 'selectImageFromPhotoLibrary' function : -
#IBAction func selectImageFromPhotoLibrary(sender: AnyObject) {
let alertController : UIAlertController = UIAlertController(title: "Camera / Photo Album ", message: "", preferredStyle: UIAlertControllerStyle.ActionSheet)
let cameraAction : UIAlertAction = UIAlertAction(title: "Camera", style: UIAlertActionStyle.Default) { (UIAlertAction) -> Void in
if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)) {
self.imagePicker.sourceType = UIImagePickerControllerSourceType.Camera
} else {
print("Camera not available")
}
self.present()
}
alertController.addAction(cameraAction)
let photoLibraryAction : UIAlertAction = UIAlertAction(title: "Photo Library", style: UIAlertActionStyle.Default) { (UIAlertAction) -> Void in
if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary)) {
self.imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
} else {
print("Photo Library not available")
}
self.present()
}
alertController.addAction(photoLibraryAction)
alertController.popoverPresentationController?.sourceView = view
alertController.popoverPresentationController?.sourceRect = view.frame
presentViewController(alertController, animated: true, completion: nil)
}
...
...
// After you are done picking up image , this function will be automatically be called.
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
print("info reached")
imagePicker.dismissViewControllerAnimated(true, completion: nil)
//Now do whatever you want to do with your picked image.
}
//For presenting the imagePicker Controller.
func present(){
self.presentViewController(self.imagePicker, animated: true, completion: nil)
}
}
If you get stuck on how to extract image just check this link out : Swift - UIImagePickerController - how to use it?
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImagePickerController_Class/

Resources