Im working in an application which requires the camera. The way Im opening it is this:
let Picker = UIImagePickerController()
Picker.delegate = self
Picker.sourceType = .camera
present(Picker, animated: true, completion: nil)
Everything works perfectly, this is the result which I get:
What I would like to do now is replace that "Cancel" button for a button which let the user select a photo from his photolibrary. I have been reading a lot but I still do not get a solution.
Thank to everyone
You can do it instead of that
#IBAction func buttonOnClick(_ sender: 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.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(UIImagePickerControllerSourceType.camera))
{
imagePicker.sourceType = UIImagePickerControllerSourceType.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 = UIImagePickerControllerSourceType.photoLibrary
imagePicker.allowsEditing = true
self.present(imagePicker, animated: true, completion: nil)
}
Make sure you are doing this 2 things:
Specifying the content type you are looking for:
Picker.mediaTypes = [KUTTypeImage as String, KUTTypeMovie as String], for example to select both videos and images.
That you added in your info.plist the camera permission description Privacy - Camera Usage Description
Related
I am using Swift 5 code and in code I have to capture image. My source type would be .camera or .photoLibrary. I have perfectly set everything even the permission settings in Info.plist but for unseen reason photo library is not accessible for selecting image. Only camera option is available every time. Please suggest and look into my code what am I doing wrong?
Permission Info.plist:
Privacy - Photo Library Additions Usage Description
Privacy - Photo Library Usage Description
Privacy - Media Library Usage Description
Privacy - Camera Usage Description
Code:
var imagePicker: UIImagePickerController!
enum ImageSource {
case photoLibrary
case camera
}
//MARK: - Take image
func takePhoto() {
guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
selectImageFrom(.photoLibrary)
return
}
selectImageFrom(.camera)
}
func selectImageFrom(_ source: ImageSource){
imagePicker = UIImagePickerController()
imagePicker.delegate = self
switch source {
case .camera:
imagePicker.sourceType = .camera
case .photoLibrary:
imagePicker.sourceType = .photoLibrary
}
present(imagePicker, animated: true, completion: nil)
}
You always prioritize camera in your guard
//MARK: - Take image
func takePhotoLib() {
guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else {
return
}
selectImageFrom(.photoLibrary)
}
//MARK: - Take image
func takePhotoCamera() {
guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
return
}
selectImageFrom(.camera)
}
func selectimage(_ sender: UIButton)
{
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Take Photo", style: .default, handler: { _ in
self.openCamera()
}))
alert.addAction(UIAlertAction(title: "Choose Photo", 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 in 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)
}
//MARK: - Open the camera
func openCamera(){
if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)){
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
//If you dont want to edit the photo then you can set allowsEditing to false
// imagePicker.allowsEditing = true
imagePicker.delegate = self
imagePicker.modalPresentationStyle = .overCurrentContext
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(){
if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary)){
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
self.tabBarController?.tabBar.isHidden = true
//If you dont want to edit the photo then you can set allowsEditing to false
// imagePicker.allowsEditing = true
imagePicker.delegate = self
imagePicker.modalPresentationStyle = .overCurrentContext
self.present(imagePicker, animated: true, completion: nil)
}
I think this function is shorter and reduces the extra code.
func selectImageFrom(_ source: UIImagePickerController.SourceType) {
guard UIImagePickerController.isSourceTypeAvailable(source) else {
return
}
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = source
present(imagePicker, animated: true, completion: nil)
}
Change the argument type from ImageSource to UIImagePickerController.SourceType
func selectImageFrom(_ source: UIImagePickerController.SourceType){
imagePicker = UIImagePickerController()
imagePicker.delegate = self
switch source {
case .camera:
imagePicker.sourceType = .camera
case .photoLibrary:
imagePicker.sourceType = .photoLibrary
}
present(imagePicker, animated: true, completion: nil)
}
It should work now.
Sorry, you seem to check whether the device have a camera and then proceed to select that. Show an action sheet for the user to select one of them. It would work.
use this function:
func showOptions(sender: AnyObject) {
let alertController = UIAlertController.init(title: "Choose Option", message: "", preferredStyle: .actionSheet)
let cameraAction = UIAlertAction.init(title: "Camera", style: .default) { (action) in
self.selectImageFrom(.camera)
}
alertController.addAction(cameraAction)
let photoLibraryAction = UIAlertAction.init(title: "Photo Library", style: .default) { (action) in
self.selectImageFrom(.photoLibrary)
}
alertController.addAction(photoLibraryAction)
let cancelAction = UIAlertAction.init(title: "Cancel", style: .cancel) { (action) in
}
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
I have a view with 2 UIImageViews and 2 buttons in order to select 2 different pictures with UIImagePickerViewController. It actually works but when I upload 1 image the other UIView Image is also selecting the same image.
What am I doing wrong ?
}
#IBAction func uploadButton(_ 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: "Cancel", style: .cancel, handler: nil))
self.present(actionSheet, animated: true, completion: nil)
}
#IBAction func coverButton(_ 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: "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
profileImage.image = image
backgroundImage.image = image
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
You have duplicate code and no way to determine which image view to update after a picture is selected/taken. You need to refactor your code.
Add a property to your class:
var chosenImageView: UIImageView?
Then put your common code into its own method:
function selectPhoto() {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let actionSheet = UIAlertController(title: "Photo Source", message: "Choose a source", preferredStyle: .actionSheet)
if UIImagePickerController.isSourceTypeAvailable(.camera) {
actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (action:UIAlertAction) in
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)
}
Note how the Camera button isn't shown if there is no camera.
Then refactor your two actions:
#IBAction func uploadButton(_ sender: Any) {
chosenImageView = profileImage
selectPhoto()
}
#IBAction func coverButton(_ sender: Any) {
chosenImageView = backgroundImage
selectPhoto()
}
And lastly the delegate methods:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
chosenImageView?.image = image
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
In iOS Swift 3.1 I'm trying to access the camera, the same way I have done successfully in other apps. However, in this one particular app, it always crashes on the self.present(imagePicker, animated: true, completion: nil) line. The message in the console is Message from debugger: Terminated due to signal 9. Does this usually signal a memory related error?
#IBAction func onChooseImageClick(_ sender: AnyObject) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.savedPhotosAlbum){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
//Create the AlertController and add Its action like button in Actionsheet
let actionSheetControllerForImage: UIAlertController = UIAlertController(title: "Please select", message: "Option to select", preferredStyle: .actionSheet)
let cancelActionButton: UIAlertAction = UIAlertAction(title: "Cancel", style: .cancel) { action -> Void in
print("Cancel")
}
actionSheetControllerForImage.addAction(cancelActionButton)
let cameraActionButton: UIAlertAction = UIAlertAction(title: "Camera", style: .default)
{ action -> Void in
print("Camera")
if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)) {
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
let mediaTypes:[String] = [kUTTypeImage as String]
imagePicker.mediaTypes = mediaTypes
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
} else {
let alertController = UIAlertController(title: "error", message: "Camera not found!", preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .cancel) { action in
// ...
}
alertController.addAction(OKAction)
self.present(alertController, animated: true)
}
}
actionSheetControllerForImage.addAction(cameraActionButton)
let galleryActionButton: UIAlertAction = UIAlertAction(title: "Image Gallery", style: .default)
{ action -> Void in
imagePicker.sourceType = UIImagePickerControllerSourceType.savedPhotosAlbum;
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
actionSheetControllerForImage.popoverPresentationController?.sourceView = self.view
actionSheetControllerForImage.addAction(galleryActionButton)
===> self.present(actionSheetControllerForImage, animated: true, completion: nil)
}
}
You need a string in your plist file that explains why your app need permission to use the camera. There's a great summary of these strings in the question at iOS 10 - Changes in asking permissions of Camera, microphone and Photo Library causing application to crash, with a list you can copy from in the answer at https://stackoverflow.com/a/40734360/968577
Without the required strings, your app will crash in this manner. However, the console output will explain what the problem is.
Try like this i hope it would be helpful!!
Add these two points in info.plist first
Privacy - Camera Usage Description
Privacy - Photo Library Usage Description
Add these two delegates in your class file
UIImagePickerControllerDelegate
UINavigationControllerDelegate
#IBAction func onclickImageAction(_ sender: Any){
print("onclickImageAction method called here")
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.isEditing = false
let actionSheet = UIAlertController(title: "Select Profile Photo", message: "", preferredStyle: UIAlertControllerStyle.actionSheet)
let libButton = UIAlertAction(title: "Select photo from library", style: UIAlertActionStyle.default){ (libSelected) in
print("library selected")
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
self.present(imagePicker, animated: true, completion: nil)
}
actionSheet.addAction(libButton)
let cameraButton = UIAlertAction(title: "Take a picture", style: UIAlertActionStyle.default) { (camSelected) in
if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera))
{
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
self.present(imagePicker, animated: true, completion: nil)
}
else
{
actionSheet.dismiss(animated: false, completion: nil)
let alert = UIAlertController(title: "Error", message: "There is no camera available", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Okay", style: .default, handler: { (alertAction) in
alert.dismiss(animated: true, completion: nil)
}))
}
}
actionSheet.addAction(cameraButton)
let cancelButton = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel) { (cancelSelected) in
print("cancel selected")
}
actionSheet.addAction(cancelButton)
let albumButton = UIAlertAction(title: "Saved Album", style: UIAlertActionStyle.default) { (albumSelected) in
print("Album selected")
imagePicker.sourceType = UIImagePickerControllerSourceType.savedPhotosAlbum
self.present(imagePicker, animated: true, completion: nil)
}
actionSheet.addAction(albumButton)
self.present(actionSheet, animated: true, completion:nil)
}
Implement these delegate method
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{if let PickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage
{
yourimageview.image = PickedImage
dismiss(animated: true, completion: nil)
}
}
I just added exit(0) when i opened the camera settings. It's working fine
I have a problem when I want to access to the photo gallery from the user than iOS show first an alert for the permission. I have the same code in one project it show the alert in the other project iOS don't ask me for something there is only a black screen.
The real project...
The test project...
It's really weird because I use the same code...
This is my Swift code :
#IBAction func uploadImagePressed(sender: AnyObject) {
let alertController = UIAlertController(title: "Choose Image", message: "", preferredStyle: UIAlertControllerStyle.ActionSheet)
let cameraAction = UIAlertAction(title: "Camera", style: UIAlertActionStyle.Default, handler: { (alertController) -> Void in
if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
imagePicker.sourceType = .Camera
imagePicker.mediaTypes = [kUTTypeImage as String]
imagePicker.modalPresentationStyle = .FullScreen
self.presentViewController(imagePicker, animated: true, completion: nil)
}else{
print("Camera not available on iDevice...")
}
})
let gallery = UIAlertAction(title: "Gallery", style: UIAlertActionStyle.Default, handler: { (alertController) -> Void in
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
imagePicker.sourceType = .PhotoLibrary
imagePicker.mediaTypes = [kUTTypeImage as String]
imagePicker.modalPresentationStyle = .Popover
self.presentViewController(imagePicker, animated: true, completion: nil)
})
let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: { (alertController) -> Void in})
alertController.addAction(cameraAction)
alertController.addAction(gallery)
alertController.addAction(cancel)
self.presentViewController(alertController, animated: true, completion: nil)
}
there is no error but when i test it on real phone, even in the simulation, it only display a lock image and "This app does not have access to your photos or videos you can enable access in Privacy settings" but when i turn to setting I couldn't find my app in privacy setting. Where did i go wrong?
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = false
let selectedSourceAction = UIAlertController(title: "What source do you want to access?", message: "", preferredStyle: UIAlertControllerStyle.ActionSheet)
let fromPhotoLibrary = UIAlertAction(title: "Photo Library", style: UIAlertActionStyle.Default, handler: {(action: UIAlertAction!) -> Void in
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(imagePicker, animated: true, completion: nil)
})
let fromCamera = UIAlertAction(title: "Camera", style: UIAlertActionStyle.Default, handler: {(action: UIAlertAction!) -> Void in
imagePicker.sourceType = UIImagePickerControllerSourceType.Camera
self.presentViewController(imagePicker, animated: true, completion: nil)
})
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
selectedSourceAction.addAction(fromPhotoLibrary)
selectedSourceAction.addAction(fromCamera)
selectedSourceAction.addAction(cancelAction)
self.presentViewController(selectedSourceAction, animated: true, completion: nil)
}
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
imageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
imageView.contentMode = UIViewContentMode.ScaleAspectFit
imageView.clipsToBounds = true
dismissViewControllerAnimated(true, completion: nil)
}
Such bug may happen on IOS 9 when your application's Info.plist file contains a key: "CFBundleDisplayName" with empty string value.