Import image based off what UIIMageView is equal to nil - swift

I have my app setup to import a picture. If there isn't a picture in the first UIImageView puts the imported picture there. If the first UIImageView does have something in it put picture in the second UIImageView. Finally if the first and second UIImageView put the picture in the third
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
if picture.image == nil {
picture.image = image
} else if picture.image == image {
picture2.image = image
} else if picture2.image == image {
picture3.image = image
}
self.dismiss(animated: true, completion: nil)
}
}

Try to replace == image to == nil in the second and third if statement because every picture should have different images.

Related

Swift - get sender of UIImagePickerController

I have 2 UIImageViews which I have added a UITapGestureRecognizer to which opens the user's camera. Once the user has selected an image, then the UIImageView that was tapped in order to access the camera should be set with the camera image.
So here is my openCamera method:
#objc func openCamera(sender: ImagePlaceHolderView) {
let picker = UIImagePickerController()
picker.allowsEditing = true
picker.delegate = self
picker.sourceType = .camera
present(picker, animated: true)
}
My UIImageViews are declared as follows:
var left = UIImageView()
var right = UIImageView()
left = createImagePlaceholder()
right = createImagePlaceholder()
private func createImagePlaceholder() -> UIImageView {
let placeholder = ImagePlaceHolderView(frame: CGRect(x: 0, y: 0, width: 90, height: 150))
placeholder.isUserInteractionEnabled = true
return placeholder
}
And then my delegate method:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.editedImage] as? UIImage else { return }
left.image = image // Here I want to set the sender's image to image
dismiss(animated: true, completion: nil)
}
I'm struggling to figure out how to set the image of the UIImageView that was tapped to this new image from the camera. I'm trying to pass the sender into the openCamera method but not sure how to extract this, as the sender seems in fact to be the UITapGestureRecognizer rather than the image that was tapped.
You'll have to store a reference to the sender and use that to set the image in the delegate method.
var imagePlaceholderView: ImagePlaceHolderView? // set the reference
#objc func openCamera(sender: UITapGestureRecognizer) {
imagePlaceholderView = sender.view as? ImagePlaceHolderView
//...
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.editedImage] as? UIImage else { return }
imagePlaceholderView?.image = image
dismiss(animated: true, completion: nil)
}

Unable to Scan QR from gallery image

I am trying to make a QR code scanner, which takes an image from the gallery on button click and show a message.
My Button function is:-
#IBAction func gallaryBtnEventListener(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary) {
pickerController.delegate = self
pickerController.sourceType = UIImagePickerController.SourceType.photoLibrary
pickerController.allowsEditing = true
self.present(pickerController, animated: true, completion: nil)
}
}
And this is the imagepickerCOntroller
private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let qrcodeImg = info[UIImagePickerController.InfoKey.originalImage.rawValue] as? UIImage {
let detector:CIDetector=CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])!
let ciImage:CIImage=CIImage(image:qrcodeImg)!
var qrCodeLink=""
let features=detector.features(in: ciImage)
for feature in features as! [CIQRCodeFeature] {
qrCodeLink += feature.messageString!
}
if qrCodeLink=="" {
print("nothing")
}else{
print("message: \(qrCodeLink)")
}
}
else{
print("Something went wrong")
}
self.dismiss(animated: true, completion: nil)
}
When I run this code I successfully can select an image from the gallery, but it's print nothing.
Now I need help regarding this. One more thing, I did not add any imageView.
It's because you're adding the private access modifier for the UIImagePickerControllerDelegate method imagePickerController(_:,didFinishPickingMediaWithInfo:). Remove the private keyword in front of the method and the delegate will start to work fine. Also, do not copy/paste the delegate methods you're using the old version, here's the newer version:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let qrcodeImg = info[.originalImage] as? UIImage {
//...
}
}

Creating an image format with an unknown type is an error while capturing image from gallery Swift

Im trying to get image from gallery in Swift.
func showPicker(type : UIImagePickerControllerSourceType) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = type
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
then:
self.showPicker(type: .savedPhotosAlbum)
However, when i enter gallery on my device and pick photo nothing happen, instead in log it says : [Generic] Creating an image format with an unknown type is an error
How to dismiss gallery and save image?
UIImagepickerView
set delegate UIImagePickerControllerDelegate, UINavigationControllerDelegate
let imagePicker = UIImagePickerController()
//in did load
imagePicker.delegate = self
// MARK: - UIImagePickerControllerDelegate Methods
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
imgview.image = image
} else{
print("Something went wrong")
}
dismiss(animated: true, completion: nil)
}

Set image of UIImageView using gestureRecognizer

I am asking if it is possible to set the image of a UIImageView using a gestureRecognizer, or is it necessary to overlay a button on top of the UIImageView.
I have an outlet collection of UIImageViews, called imageViews. There are four of these, and their tags have been set from 1 to 4. In my viewDidLoad, to add the gesture recognizer to each of the image views in the collection, i have used:
override func viewDidLoad() {
super.viewDidLoad()
for i in (0..<imageViews.count) {
let imageViewTapped = UITapGestureRecognizer(target: self, action: #selector(selectImage(tap:)))
imageViewTapped.numberOfTapsRequired = 1
imageViews[i].addGestureRecognizer(imageViewTapped)
}
}
Next, I created my gestureRecognizer as a function in the viewController class. This is where the image picker controller is created and where the image view that was tapped is identified:
func selectImage(tap: UITapGestureRecognizer) {
var imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = false
imagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
self.present(imagePicker, animated: true, completion: nil)
guard let viewTappedTag = tap.view?.tag else {return}
self.selectedImageView = imageViews[viewTappedTag - 1]
}
selectedImageView is a variable in the viewController class with a type of UIImageView. My thinking was that this variable could hold the UIImageView that was tapped, which is identified by the gestureRecognizer, as shown above. This could then be passed to the delegate later on.
Next, I created the delegates, the didFinishPickingMediaWithInfo and didCancel, though I will only show the former for brevity. Both were created inside the viewController class:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var chosenImage = UIImage()
chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
self.selectedImageView.image = chosenImage
dismiss(animated: true, completion: nil)
}
Unfortunatley, the image of the image view that was tapped is not updated to the one that was chosen from the library. What is the correct way to do this? And I feel as though I am bloating my viewController with all of this code, can this be moved to a seperate class? Am i wrong in doing it like this, and instead one should just overlay a button?
EDIT
The best I could come up with so far is a switch statement in my imagePickerController, where imageViewOne, imageViewTwo etc are outlets for each UIImageView:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var chosenImage = UIImage()
chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
switch self.viewTappedTag {
case 1:
imageViewOne.image = chosenImage
case 2:
imageViewTwo.image = chosenImage
case 3:
imageViewThree.image = chosenImage
case 4:
imageViewFour.image = chosenImage
default:
imageViewOne.image = chosenImage
}
dismiss(animated: true, completion: nil)
}
where viewTappedTag is a viewController class variable, the value of which is defined by the tag of the view that was tapped and is set in the gestureRecognizer. Can anyone improve on this?
Update the code as following
Declare a variable in the class as follows
var selectedImageViewIndex = 0 //by default selected image view is 0th image view
func selectImage(tap: UITapGestureRecognizer) {
var imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = false
imagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
self.present(imagePicker, animated: true, completion: nil)
guard let viewTappedTag = tap.view?.tag else {return}
self.selectedImageView = imageViews[viewTappedTag - 1]
//Add the following line
self.selectedImageViewIndex = viewTappedTag - 1
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var chosenImage = UIImage()
chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
self.selectedImageView.image = chosenImage
//Add the following line
self.imageView[self.selectedImageViewIndex].image = chosenImage
dismiss(animated: true, completion: nil)
}
Though I would advice not to use viewTappedTag - 1 and instead get the value of index and tapped image tag from a mapped object.
In the end I used a switch statement to achieve my goal:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var chosenImage = UIImage()
chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
switch self.viewTappedTag {
case 1:
imageViewOne.image = chosenImage
case 2:
imageViewTwo.image = chosenImage
case 3:
imageViewThree.image = chosenImage
case 4:
imageViewFour.image = chosenImage
default:
imageViewOne.image = chosenImage
}
dismiss(animated: true, completion: nil)
}

Swift displaying image in viewdidappear cannot be replaced by picking new image

I use firebase as my back end and I have a displaying facebook photo image function in viewdidappear so the profile image will display when the user is at the viewcontroller. My problem is whenever user want to change the profile Image by image picker it will display the "picked image" for 1 sec only and turn back to facebook image.
I think the problem is the displaying facebook photo image function is in the viewdidappear? How can I solve it?
override func viewdidappear(){
super.viewdidappear(animated)
self.displayProfilePic(user)
}
func displayProfilePic(user: FIRUser?){
let photoURL = user?.photoURL
struct last {
static var photoURL: NSURL? = nil
}
last.photoURL = photoURL; later one.
if let photoURL = photoURL {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {
let data = NSData.init(contentsOfURL: photoURL)
if let data = data {
let image = UIImage.init(data: data)
dispatch_async(dispatch_get_main_queue(), {
if (photoURL == last.photoURL) {
self.profilePic.image = image
}
})
}
})
} else {
profilePic.image = UIImage.init(named: "DefaultPic")
}
image Picker method
func openGallary(){
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum){
print("Pick Photo")
self.imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.imagePicker.allowsEditing = true
self.presentViewController(self.imagePicker, animated: true, completion: nil)
}
}
func openCamera(){
if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){
self.imagePicker.sourceType = UIImagePickerControllerSourceType.Camera
self.imagePicker.allowsEditing = true
self.presentViewController(self.imagePicker, animated: true, completion: nil)
}else{
print("you got no camara")
}
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMeddiaWithInfo info: [String :AnyObject]){
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
profilePic.contentMode = .ScaleAspectFit
profilePic.image = pickedImage
}
dismissViewControllerAnimated(true, completion: nil)
}
I am not sure why the image picker's picked image cannot be replaced.
I think the problem is the displaying facebook photo image function is in the viewdidappear
This is correct. viewDidAppear is called every time the view is shown again after a VC that was covering it is dismissed (e.g. the image picker).
You could do this in viewDidLoad instead -- which is called just once when the VC is loaded -- and is not called again when the imagePicker is done.
If you can't, then you need to keep track that the imagePicker replaced the image and that it should not be replaced again with the FB image when viewDidAppear is called.