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.
Related
I have set up the insertion of the image from the photo library and now I am trying to let the user also select a video from the photo library or camera roll in iOS. I have written the following code:-
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBAction func didTapOnImageView(sender: UITapGestureRecognizer) {
//call Alert function
self.showAlert()
}
//Show alert to selected the media source type.
private func showAlert() {
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)
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
imagePickerController.mediaTypes = ["public.image", "public.movie"]
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?.image20 = self?.imageView.image
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}
It works perfectly fine for choosing the image and displaying it, but, now I am able to select the video but, not display it. Could anyone please help on what shall I include in the imagePickerController delegate to obtain the video URL and display it? Thanks for the help! Appreciate it!
You can definitely catch the vide data from your imagePicker, like so:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
picker.dismiss(animated: true) {
if let image = info[.originalImage] as? UIImage,
let data = image.jpegData(compressionQuality: 0.8) {
}
}
if let videoURL = info[.mediaURL] as? URL {
do {
let videoData = try Data(contentsOf: videoURL, options: .mappedIfSafe)
} catch {
print("Error: \(error.localizedDescription)")
}
}
}
Now, after fetching the Data of your selected video file, your next step is to do the research of playing the video data in a view. You can start from this: Implementing video view in the Storyboard
But take heed of the age of that link, it's from 2015, but it should still help you out.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
videoURL = info[UIImagePickerController.InfoKey(rawValue: "UIImagePickerControllerReferenceURL")] as? URL
}
after getting videoURL you can pass it to AVPlayer to play it.
let player = AVPlayer(url: videoURL)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
present(playerViewController, animated: true) {
playerViewController.player!.play()
}
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!
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)
}
This question already has an answer here:
Picking two different images in the same view controller using imagePickerController in Swift
(1 answer)
Closed 4 years ago.
I am adding 2 function UITapGestureRecognizer for my 2 UIImage for displaying diffrent picture each UIImage.
So when I tap one of my UIImage, UIAlertController will show and give 2 option for adding a picture (using Camera or using Library)
But when I'm adding the picture, both of them is displaying same picture (when I using imagePickerController
and after I add if else statement, the picture is only displayed on if statement even when I tap on the second UIImage
For example:
I've 2 UIImage named imageView1.image and imageView2.image
I tap on my first imageView1.image, UIAlertController does show option (camera and library)
I choose library and select image1.jpg
After i select image1.jpg, both imageView1.image and imageView2.image displaying same picture.
After I'm adding if else statement in the func imagePickerController, the image1.jpg is only displayed on the if statement... Even i tap on the imageVIew2.image
But, what I want is...
When i tap imageView1.image and select image1.jpg, imageView1.image displaying image1.jpg and imageView2.jpg isnt displaying anything.
Here's my code (without if else):
extension KUYPEP {
//pencetGambarnya1 for imageView1.image
#objc func pencetGambarnya1(tapGestureRecognizer1: UITapGestureRecognizer) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let gambarDipencet1 = tapGestureRecognizer1.view as! UIImageView
let act1 = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
act1.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(UIAlertAction) in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePickerController.sourceType = .camera;
self.present (imagePickerController, animated: true, completion: nil)
} else {
print ("Camera ruksak")
}
}))
act1.addAction(UIAlertAction(title: "Library", style: .default, handler: {(UIAlertAction) in
imagePickerController.sourceType = .photoLibrary
self.present(imagePickerController, animated: true, completion: nil)
}))
act1.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: {(UIAlertAction)in}))
self.present(act1, animated: true, completion: nil)
print ("berhasil11")
}
//pencetGambarnya2 for imageView2.image
#objc func pencetGambarnya2(tapGestureRecognizer2: UITapGestureRecognizer) {
let imagePickerController2 = UIImagePickerController()
imagePickerController2.delegate = self
let gambarDipencet2 = tapGestureRecognizer2.view as! UIImageView
let act2 = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
act2.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(UIAlertAction) in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePickerController2.sourceType = .camera;
self.present (imagePickerController2, animated: true, completion: nil)
} else {
print ("Camera ruksak")
}
}))
act2.addAction(UIAlertAction(title: "Library", style: .default, handler: {(UIAlertAction) in
imagePickerController2.sourceType = .photoLibrary
self.present(imagePickerController2, animated: true, completion: nil)
}))
act2.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: {(UIAlertAction)in}))
self.present(act2, animated: true, completion: nil)
print ("berhasil22")
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image1 = info[UIImagePickerControllerOriginalImage] as! UIImage
imageView1.image = image1
let image2 = info[UIImagePickerControllerOriginalImage] as! UIImage
imageView2.image = image2
picker.dismiss(animated: true, completion: nil)
print ("Slavic Hardbass")
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}
And here's my viewDidLoad
let tapGestureRecognizer1 = UITapGestureRecognizer(target: self, action: #selector(pencetGambarnya1(tapGestureRecognizer1:)))
imageView1.isUserInteractionEnabled = true
imageView1.addGestureRecognizer(tapGestureRecognizer1)
let tapGestureRecognizer2 = UITapGestureRecognizer(target: self, action: #selector(pencetGambarnya2(tapGestureRecognizer2:)))
imageView2.isUserInteractionEnabled = true
imageView2.addGestureRecognizer(tapGestureRecognizer2)
Create one public UIImage named targetImage and do like the following,
assign the reference of image1 or image2 to targetImage just before presenting imagePickerController. When finished picking the image, just set the picked image to targetImage. You can see in the following code, i have set targetImage = imageView1.
act1.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(UIAlertAction) in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePickerController.sourceType = .camera;
targetImage = imageView1
self.present (imagePickerController, animated: true, completion: nil)
} else {
print ("Camera ruksak")
}
}))
And do the same for imageView2 as well,
After that modify code to set picked media like this,
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image1 = info[UIImagePickerControllerOriginalImage] as! UIImage
targetImage.image = image1
picker.dismiss(animated: true, completion: nil)
print ("Slavic Hardbass")
}
I have not tested this, but this should work.
Try this Code. Hope it works for you
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if picker == imagePickerController
{
let image1 = info[UIImagePickerControllerOriginalImage] as! UIImage
imageView1.image = image1
}
else
{
let image2 = info[UIImagePickerControllerOriginalImage] as! UIImage
imageView2.image = image2
}
picker.dismiss(animated: true, completion: nil)
print ("Slavic Hardbass")
}
Solve it by adding var in the class using this code
answer
Thank you for replying.
I have a image view inside the view controller. I want to set this image when user selects an image from gallery.
I tried this code:
#IBOutlet var profilePicture: UIImageView!
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
self.dismissViewControllerAnimated(true, completion:nil)
println("image selected from gallery")
self.profilePicture.image = image
}
It prints debug message to console but it is not changing the image. How can I fix this ?
You just forgot to assign image you got from gallery to your UIImageView.
#IBOutlet var profilePicture: UIImageView!
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
profilePicture.image = image
self.dismissViewControllerAnimated(true, completion: { () -> Void in
})
println("image selected from gallery")
self.profilePicture.image=image
}
Can you try this code:
#IBOutlet var profilePicture: UIImageView!
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
self.dismissViewControllerAnimated(true, completion: { () -> Void in
})
println("image selected from gallery")
dispatch_async(dispatch_get_main_queue()) {
self.profilePicture.image=image
}
}
#IBAction func chooseProfilePicBtnClicked(sender: AnyObject) {
let alert:UIAlertController=UIAlertController(title: "Choose Image", message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet)
let cameraAction = UIAlertAction(title: "Camera", style: UIAlertActionStyle.Default)
{
UIAlertAction in
self.openCamera()
}
let gallaryAction = UIAlertAction(title: "Gallary", style: UIAlertActionStyle.Default)
{
UIAlertAction in
self.openGallary()
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel)
{
UIAlertAction in
}
// Add the actions
picker.delegate = self
alert.addAction(cameraAction)
alert.addAction(gallaryAction)
alert.addAction(cancelAction)
self.presentViewController(alert, animated: true, completion: nil)
}
func openCamera(){
if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){
picker.sourceType = UIImagePickerControllerSourceType.Camera
self .presentViewController(picker, animated: true, completion: nil)
}else{
let alert = UIAlertView()
alert.title = "Warning"
alert.message = "You don't have camera"
alert.addButtonWithTitle("OK")
alert.show()
}
}
func openGallary(){
picker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(picker, animated: true, completion: nil)
}
//MARK:UIImagePickerControllerDelegate
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]){
picker .dismissViewControllerAnimated(true, completion: nil)
imageViewRef.image=info[UIImagePickerControllerOriginalImage] as? UIImage
}
func imagePickerControllerDidCancel(picker: UIImagePickerController){
print("picker cancel.")
}
To display a selected image using UIImagePickerController use the following code:
// Add these protocols into your class declaration
UIImagePickerControllerDelegate, UINavigationControllerDelegate
// Set the delegate
#IBAction func presentViewImagePicker(sender: AnyObject) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
presentViewController(imagePicker, animated: true, completion: nil)
}
// Use these two methods from UIImagePickerControllerDelegate
Check the documentation https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImagePickerControllerDelegate_Protocol/index.html
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageRetrieved.contentMode = .ScaleAspectFill
imageRetrieved.image = pickedImage
}
self.dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
self.dismissViewControllerAnimated(true, completion: nil)
}
Hope it helps
The delegate method you are using is deprecated. You should replace it with this:
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info
Use this link to learn which keys you need to use to retrieve the image from the dictionary.