1

i'm new to the whole iOS development. I would like to ask, I have a vc with an image view and a button ( text fields & labels are not the problem) and i want when the user taps to choose or to take a profile photo. The photo that the user will take or choose, it's going to replace my static image view. How i can achieve this? Here is the vc

and here is my code:

import UIKit

class CreateAccountViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextFieldDelegate {

  @IBOutlet weak var profilePic: UIImageView!
  @IBOutlet weak var nameTextField: UITextField!
  @IBOutlet weak var emailTxtField: UITextField!
  @IBOutlet weak var pwdTextFld: UITextField!
  @IBOutlet weak var retypePwdTextField: UITextField!
  @IBOutlet weak var startEarningRewardsBtn: UIButton!
  let myPickerController = UIImagePickerController()

  override func viewDidLoad() {
    super.viewDidLoad()
    startEarningRewardsBtn.layer.cornerRadius = 4
    UIApplication.sharedApplication().statusBarStyle = .Default
    myPickerController.delegate = self
    let tapGesture = UITapGestureRecognizer(target: self, action:
    "imageTapped:")

    profilePic.addGestureRecognizer(tapGesture)
    profilePic.userInteractionEnabled = true

  }


  func imageTapped(gesture:UIGestureRecognizer) {
    if let _ = gesture.view as? UIImageView {
    print("Image Tapped")
    showActionSheet()
    }
  }

  func camera() {
   let myPickerController = UIImagePickerController()
   myPickerController.delegate = self;
   myPickerController.sourceType =  UIImagePickerControllerSourceType.Camera

   self.presentViewController(myPickerController, animated: true, completion: nil)

  }

 func photoLibrary()  {

   let myPickerController = UIImagePickerController()
   myPickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary

   self.presentViewController(myPickerController, animated: true, completion: nil)

 }

  func showActionSheet() {
    let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet)

    actionSheet.addAction(UIAlertAction(title: "Camera", style: UIAlertActionStyle.Default, handler: { (alert:UIAlertAction!) -> Void in
  self.camera()
}))

    actionSheet.addAction(UIAlertAction(title: "Gallery", style: UIAlertActionStyle.Default, handler: { (alert:UIAlertAction!) -> Void in
  self.photoLibrary()
}))

    actionSheet.addAction(UIAlertAction(title: "Cancel", style:      UIAlertActionStyle.Cancel, handler: nil))

    self.presentViewController(actionSheet, animated: true, completion: nil)

  }

  func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject!]) {

    if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {

      profilePic.contentMode = .ScaleAspectFit
      profilePic.image = pickedImage
  }
  self.dismissViewControllerAnimated(true, completion: nil)

  }

  func imagePickerControllerDidCancel(picker: UIImagePickerController) {
  dismissViewControllerAnimated(true, completion: nil)
    }

}
Blake Lockley
  • 2,931
  • 1
  • 17
  • 30
  • is the issue that when you finishing picking the image (from the camera roll/ camera) the view controller with the image you want to change is disappearing? – Blake Lockley Mar 13 '16 at 23:01
  • 1
    Possible duplicate of [How to get image from UIImagePickerController and Pass to next VC](http://stackoverflow.com/questions/30574533/how-to-get-image-from-uiimagepickercontroller-and-pass-to-next-vc) – Cai Mar 13 '16 at 23:04
  • @BlakeLockley No. When the user picks or take a photo i need this red photo that i have attached to this image view to change to the image that the user chose. – Agisilaos Tsaraboulidis Mar 13 '16 at 23:12
  • @ΤσαραμπουλιδηςΑγησιλαος i understand what you are trying to achieve but you have not mentioned what it wrong with what you're currently doing. Is the code you included in your question part of your view controller that contains the "static picture" - if so the problem is that you are dismissing that view controller instead of the image picker controller. If this is the problem i will post an answer explaining the solution. – Blake Lockley Mar 13 '16 at 23:16
  • @Zhi-WeiCai I don't think that is the same question! i checked that question before i asked mine because i didn't want to make a duplicate question. – Agisilaos Tsaraboulidis Mar 13 '16 at 23:16
  • @BlakeLockley The problem with my current code is that all works well until i pick an image from the gallery or take a picture with the camera. When i pick an image, the static image view ( the red one ) does not change. And i want to change to the image that i chose. – Agisilaos Tsaraboulidis Mar 13 '16 at 23:19
  • @ΤσαραμπουλιδηςΑγησιλαος when you debug does the if let statement get executed, os? also can you show us where you declared `profilePic`. Also it seems you're dismissing the wrong view controller. What class if the provided code block in? – Blake Lockley Mar 13 '16 at 23:33
  • @BlakeLockley Yes i don't have any problem when i'm running the code. I updated the question so the outlets can be visible. The class that the code is in it: class CreateAccountViewController – Agisilaos Tsaraboulidis Mar 13 '16 at 23:41
  • put a breakpoint inside the `picker: _, didFinishPickingMediaWithInfo: _` method, does it reach that point? - if not: have you made the `CreateAccountViewController` conform to the `UIImagePickerControllerDelegate` protocol and also set `myPickerController.delegate = self` please post the whole class - put leave out the body of irrelavant methods not just the outlets – Blake Lockley Mar 13 '16 at 23:51
  • @ΤσαραμπουλιδηςΑγησιλαος ^ – Blake Lockley Mar 14 '16 at 00:12
  • @BlakeLockley I updated the code check it out! – Agisilaos Tsaraboulidis Mar 14 '16 at 00:19
  • @ΤσαραμπουλιδηςΑγησιλαος thanks mate, i edited the indentation of your code as i was finding it slightly difficult to read, I think ik what is wrong ill work on an answer now – Blake Lockley Mar 14 '16 at 00:36
  • @ΤσαραμπουλιδηςΑγησιλαος please put a print statement inside your `didFinishPickingMediaWithInfo` method and tell me if it is being printed – Blake Lockley Mar 14 '16 at 00:37
  • Meta comment: To get most out of Stack Overflow, you should ask specific questions that have a distinct answer and list what you've tried so far and how it failed. – flohei Mar 14 '16 at 10:57

3 Answers3

1

I usually do it like this when working with the UIAlertController:

1. Set up the alert

let alertController = UIAlertController(title: "Change Photo", message: "To change your photo, you can:", preferredStyle: .ActionSheet)

let takePhotoAction = UIAlertAction(title: "Take Photo", style: .Default, handler: {
    (alertAction) -> Void in
        if UIImagePickerController.isCameraDeviceAvailable(.Front) {
            let imagePicker = UIImagePickerController()
            imagePicker.delegate = self
            imagePicker.sourceType = .Camera

            self.presentViewController(imagePicker, animated: true, completion: nil)
        }
    })

let pickPhotoAction = UIAlertAction(title: "Pick Photo", style: .Default, handler: {
    (alertAction) -> Void in
        if UIImagePickerController.isSourceTypeAvailable(.PhotoLibrary) {
            let imagePicker = UIImagePickerController()
            imagePicker.delegate = self
            imagePicker.sourceType = .PhotoLibrary

            self.presentViewController(imagePicker, animated: true, completion: nil)
        }
    })

alertController.addAction(takePhotoAction)
alertController.addAction(pickPhotoAction)

self.presentViewController(alertController, animated: true, completion: nil)

Don't forget to set the delegate to receive the picked or taken photo afterwards. This is pretty much what Blake said.

2. Take the image

In the delegate function I take the image and do whatever I want with it. You could, for example, use it for a UIImageView.

func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {     
    self.imageView.image = image
    self.dismissViewControllerAnimated(true)
}

That's pretty much it.

flohei
  • 5,248
  • 10
  • 36
  • 61
0

In your photoLibary and camera methods you are declaring myPickerController due to shadowing the the myPickerController that you declared within the myPickerController and created in the init method is not actually ever being called. Due to this once the method photoLibary and camera are finished there are no more references to the local instance of myPickerController and thus when you finish picking your image the there is no reference to the delegate.

func camera() {
  myPickerController.sourceType =  UIImagePickerControllerSourceType.Camera

  self.presentViewController(myPickerController, animated: true, completion: nil)
}

func photoLibrary()  {
  myPickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary

  self.presentViewController(myPickerController, animated: true, completion: nil)
}

Also as already pointed out you will want to change this in the picker delegate methods from:

self.dismissViewControllerAnimated(true, completion: nil)

to this:

picker.dismissViewControllerAnimated(true, completion: nil)
Blake Lockley
  • 2,931
  • 1
  • 17
  • 30
-1

Your code is fine. You just have to put it inside the dispatch_async block as your updating the UI and it needs to run in the UI main queue.

if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage    
{
  dispatch_async(dispatch_get_main_queue(),
  {
    self.profilePic.contentMode = .ScaleAspectFit
    self.profilePic.image = pickedImage
  })
}
Christian Abella
  • 5,747
  • 2
  • 30
  • 42
  • why are you calling the dismissViewControllerAnimated in didFinishPickingMediaWithInfo? that is not necessary. have you tried commenting out that code and using my code? That is how I have been doing that in my app. any UI stuff must be called inside the main queue via dispatch_async. – Christian Abella Mar 14 '16 at 00:19
  • For some reason that i can't understand fore me this solution doesn't work – Agisilaos Tsaraboulidis Mar 14 '16 at 00:28
  • @ChristianAbella is correct about the `dismissViewController` being unnecessary but ui updates don't particularly need to be called in an async thread, unless you are updating ui while running something in the background, take a look at the answer here: http://stackoverflow.com/questions/16283652/understanding-dispatch-async – Blake Lockley Mar 14 '16 at 00:29
  • I have encountered this kind of problem before and wondered why the image or list is not updating and after adding a dispatch_async, it just works. I have used the UIImagePicker a lot of times and I have to call it inside the dispatch_async to update my UIImageView object. – Christian Abella Mar 14 '16 at 00:33