UIPickerView with UIActionSheet - ios

I'm new to swift and I'm trying to add a picture from the gallery/camera to an image view and also pass it backward and store it in the array. Below is what I have so far I can click the button and show me an action sheet that takes me to the gallery and the camera just don't know how to assign it to my imageView and pass the image info back.
#IBAction func addPhoto(_ sender: Any) {
showSimpleActionSheet(controller: self)
}
func showSimpleActionSheet(controller: UIViewController) {
let alert = UIAlertController(title: "Choose an image", message: "", preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (_) in
self.getImage(fromSourceType: .camera)
}))
alert.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: { (_) in
self.getImage(fromSourceType: .photoLibrary)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (_) in
}))
self.present(alert, animated: true, completion: {
})
}
extension NewViewController: UIImagePickerControllerDelegate,UINavigationControllerDelegate {
func getImage(fromSourceType sourceType: UIImagePickerController.SourceType){
if UIImagePickerController.isSourceTypeAvailable(sourceType){
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.sourceType = sourceType
self.present(imagePickerController, animated: true, completion: nil)
} else {
print("Source type isn't available")
}
}
}

When you create an image picker controller, you have to set a delegate. That delegate must conform to the UIImagePickerControllerDelegate protocol.
The image picker controller will invoke it’s delegate’s methods to notify it when the user picks an image/movie. That’s where you would accept the user-selected image and install it into your image view (or whatever it is you want to do with the image).
The delegate method that tells you what media the user selected is imagePickerController(_:didFinishPickingMediaWithInfo:).
Show us your implementation of that method.

Related

Why is photo library not displaying when I select it in swift?

Using this question I ask the user to decide whether they want to use the camera or choose an image from their phone:
//Show alert to select the media source type.
private func showAlert() {
let alert = UIAlertController(title: "Image Selection", message: "From where you want to pick this image?", preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(action: UIAlertAction) in
self.imagePicker.sourceType = .camera
}))
alert.addAction(UIAlertAction(title: "Photo Album", style: .default, handler: {(action: UIAlertAction) in
self.imagePicker.sourceType = .photoLibrary
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .destructive, handler: nil))
self.present(alert, animated: true, completion: nil)
}
Which I envoke in viewDidLoad as such:
override func viewDidLoad() {
super.viewDidLoad()
firstTextField.delegate = self
showAlert()
present(imagePicker, animated: true, completion: nil)
imagePicker.delegate = self
firstImageView.layer.cornerRadius = 8
}
However when I test this the alert pops up and I choose the photo library, but the library does not appear. I have tried using viewDidAppear but that failed to work as well. No errors appear, it just hides the alert and shows the current view controller.
You may be imagining that code comes to a stop when an alert appears. But it doesn't! And you cannot show two presented view controllers simultaneously. But that is what you are trying to do.
You are saying showAlert(), so now your alert is up, and then you are immediately saying present(imagePicker), which you cannot do because your alert is still up.
Use the action handlers of the showAlert alert to present the image picker. That way, the alert closes and the image picker opens.

Error while opening Popover Option to choose either Camera or photo Library on iPad in Xcode

I am able to open a Photo Library on an iPhone using the following code:-
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBAction func TapOnImageView(sender: UITapGestureRecognizer) {
//call Alert function
self.showAlert()
}
//Show alert to selected the media source type.
private func showAlert() {
let alert = UIAlertController(title: "Image Selection", message: "From where you want to pick this image?", preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(action: UIAlertAction) in
self.getImage(fromSourceType: .camera)
}))
alert.addAction(UIAlertAction(title: "Photo Album", style: .default, handler: {(action: UIAlertAction) in
self.getImage(fromSourceType: .photoLibrary)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .destructive, handler: nil))
self.present(alert, animated: true, completion: nil)
}
//get image from source type
private func getImage(fromSourceType sourceType: UIImagePickerController.SourceType) {
//Check is source type available
if UIImagePickerController.isSourceTypeAvailable(sourceType) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.sourceType = sourceType
self.present(imagePickerController, animated: true, completion: nil)
}
}
//MARK:- UIImagePickerViewDelegate.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
self.dismiss(animated: true) { [weak self] in
guard let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
//Setting image to your image view
self?.imageView.image = image
self?.imageView.contentMode = .scaleToFill
self?.image = self?.imageView.image
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}
But, when I am running my app on iPad, I am getting the following error:-
Thread 1: Exception: "Your application has presented a UIAlertController (<UIAlertController: 0x7ffd07875e00>) of style UIAlertControllerStyleActionSheet from App Name.ViewController (<App_Name.ViewController: 0x7ffd07635620>). The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation."
Could anyone please let me know, what can I do to open camera and Photo Library on iPad in Xcode? Thanks for the help!
Updated:
Solution:
var alertStyle = UIAlertController.Style.actionSheet
if (UIDevice.current.userInterfaceIdiom == .pad) {
alertStyle = UIAlertController.Style.alert
}
let alert = UIAlertController(title: "Image Selection", message: "From where you want to pick this image?", preferredStyle: alertStyle)
You are trying to present an UIAlertController on iPad which requires to set modalStyle to UIModalPresentationPopover and its sourceView and sourceRect. Please see this answer for more details.

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/

Enumeration as Argument for a function called in a block

i wrote a function, that takes an enumeration value as argument. I don't get any errors for the function prototype, but as soon as i try to call the function an an block, ill get an error saying "Use of unresolved identifier":
#IBAction func addButtonPressed(sender: AnyObject) {
let actionMenu = UIAlertController(title: "Take a Photo or choose an
existing one", message: nil, preferredStyle:
UIAlertControllerStyle.ActionSheet)
let takePhotoAction = UIAlertAction(title: "take Photo", style: UIAlertActionStyle.Default, handler: {(alert: UIAlertAction!) -> Void in
println("take Photo")
})
let choosePhotoAction = UIAlertAction(title: "choose an existing Photo", style: UIAlertActionStyle.Default, handler: {(alert: UIAlertAction!) -> Void in
println("choose Photo")
//getting error right here
self.displayPickerController(UIImagerPickerControllerSourceType.PhotoLibrary)
})
actionMenu.addAction(takePhotoAction)
actionMenu.addAction(choosePhotoAction)
presentViewController(actionMenu, animated: true, completion: nil)
}
// MARK: - Helper Methods
func displayPickerController(withSource: UIImagePickerControllerSourceType){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = withSource
presentViewController(imagePicker, animated: true, completion: nil)
}
You have a typo in self.displayPickerController(UIImagerPickerControllerSourceType.PhotoLibrary). You typed UIImager instead of UIImage when naming the enum.

ELCImagePickerController delegate methods not called

I'm trying to build an app using ELCImagePickerController. I found that I could select multiple pictures. However, the ELCImagePickerController delegate method was not called.
This is my code:
#IBAction func uploadImages(sender: AnyObject) {
// Create the alert controller
//var alertController = UIAlertController(title: "", message: "", preferredStyle: .Alert)
var alertController = UIAlertController(title: nil, message: nil, preferredStyle: .Alert)
// Create the actions
var takeAction = UIAlertAction(title: "Take Photos", style: UIAlertActionStyle.Default) {
UIAlertAction in
NSLog("Take Photos Pressed")
}
var selectAction = UIAlertAction(title: "Select Photos", style: UIAlertActionStyle.Default) {
UIAlertAction in
NSLog("Select photos Pressed")
var imagePicker = ELCImagePickerController(imagePicker: ())
imagePicker.maximumImagesCount = 2
imagePicker.returnsOriginalImage = false
imagePicker.returnsImage = true
imagePicker.onOrder = true
imagePicker.delegate = self
self.presentViewController(imagePicker, animated: true, completion: nil)
}
var cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) {
UIAlertAction in
NSLog("Cancel Pressed")
}
// Add the actions
alertController.addAction(takeAction)
alertController.addAction(selectAction)
alertController.addAction(cancelAction)
// Present the controller
self.presentViewController(alertController, animated: true, completion: nil)
}
}
func elcImagePickerController(picker: ELCImagePickerController!, didFinishPickingMediaWithInfo info:[AnyObject]!) {
NSLog("controller executed.")
}
You need to set the ImagePicker delegate
imagePicker.imagePickerDelegate = self
Are your NSLog statements ever getting called? One thing I notice in your trailing closure syntax is that you're using the type name versus a variable of that type. For instance, you're writing UIAlertAction in ... vs alertAction in .... You should be providing a name to be used within the closure rather than the type itself. If the rest of the closure is not executing, then the delegate is never being set, and therefore delegate methods are never called.

Resources