Swift 3 iOS 10 Reference to UIImageView to get Value for other function - ios

I'm looking for a way to add codewise a way to reference to a UIImageView's value from another function.
I'm having a function which creates a new UIImageView for each instance in an array. Moreover, it also has an UITapGestureRecognizer added which calls a function when tapped. Now I want the function, which is called upon tap, to get the instance of that array which relates to the respective UIImageView.
I hope it's clear what I want to do. :)

Let's say you have an array of images:
let myImages = [UIImage(named: "image1"), UIImage(named: image2", UIImage(named: "image3"0]
And you have these images in three separate image views:
imageViewA.image = myImages[0]
imageViewB.image = myImages[1]
imageViewC.image = myImages[2]
Also, you've set up everything correctly that each image view calls the same function on a tap (we'll call it imageViewTapped()).
All you need to do is (1) properly set the tag property of each image view to point at the array index, (2) get the view that was tapped on, and (3) retrieve the image.
imageViewA.tag = 0
imageViewB.tag = 1
imageViewC.tag = 2
func imageViewTapped(_ recognizer:UITapGestureRecognizer) {
let tappedView = recognizer.view
let sourceImage = myImages[tappedView.tag]
}
I'd recommend setting everything up in a loop (tags, tap recognizer) and adding some type-casting in the function if needed. But I can't see your code to help you with that.

Related

Detecting which ImageView has has been tapped

So i have 4 vStacks, each containing 9 ImageViews. Each ImageView represents one Card, alpha 0 is default. When a Card is Detected (with ARKit), my code sets the ImageView to alpha 1 so the user can see that the card has been scanned.
Now: I want to implement that when the user clicks on one of the ImageViews, an alert should pop up asking the user if he is sure he wants to delete the scanned card. My problem is, I have no idea what the best practice is to get the information that the card has been tapped and how to delete it without hardcoding.
In ViewDidLoad i set the images into the ImageVies like This:
//This repeats for all 36 ImageViews
imgView1.image = UIImage(named: "Eichel_6")
imgView2.image = UIImage(named: "Eichel_7")
/*When a image is detected with ARKit, this is what happens. Basically
*it pushes the corresponding reference name to an array called
* scannedCards, handles them, and removes them afterwards.
* spielPoints = gamepoints/points, spielmodus = gamemode
*/
func updateLabel() {
//print all cards in scanned cards
for card in scannedCards {
points += (DataController.shared.spielpoints[DataController.shared.spielmodus!]![card]! * DataController.shared.multCalculator[DataController.shared.spielmodus!]!)
}
scannedCards.removeAll()
}
I am a new to coding, I would be grateful if you correct me if my code snippets are bad, beside my question. Thank you in advance.
As has already been mentioned in comments, you should use a UICollectionView for this kind of work. #Fogmeister has promised to add an answer concerning that later, so I won't do that. But I can answer the actual question, even though it's not what you should do.
From your code I can see that you probably have outlets for all your imageViews (imgView1 ... imgView36) and set each image manually. To detect taps on any of these, you could do something like this:
func viewDidLoad(){
super.viewDidLoad()
let allImageViews = [imageView1, imageView2, .... imageView36]
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapImageView(gesture:)))
allImageViews.forEach({$0.addGestureRecognizer(tapGestureRecognizer)})
}
#objc func didTapImageView(gesture:UITapGestureRecognizer){
guard let imageView = gesture.view as? UIImageView else { return }
//Here you can put code that will happen regardless of which imageView was tapped.
imageView.alpha = 0.0
//If you need to know exactly which imageView was tapped, you can just check
if imageView == self.imageView1{
//Do stuff only for imageView1
}else if imageView == self.imageView2{
//...
}//....
}
Again, this is not very good practice. If you go for UICollectionView instead, you don't have to have outlets for all your imageViews and you don't have to create a gestureRecognizer for handling events. But still, I hope this helped you understand general gestures better.

Show or hide items by clicking button

I have four imageview contents in an XIB and a button that covers all my XIB. I want to make when the user tap the button, the first imageview is shown, the next tap is hidden and the second imageview is displayed and so on until all my imageview is shown / hidden. What would be the most efficient way to do it?
Save all your UIImageViews to an array, and current showing imageView to a variable, it may look like this:
var imageViews: [UIImageView] = []
var currentImageViewIndex = 0 {
didSet {
if currentImageViewIndex >= imageViews.count { currentImageViewIndex = 0 }
imageViews[oldValue].isHidden = true
imageViews[currentImageViewIndex].isHidden = false
}
}
func handleTap() {
currentImageViewIndex += 1
}
I suggest you use a state variable that contains an enum listing the various states (firstImageVisible, secondImage.... ) then you can have a function inside the enum that switches to the nextState (being the target of your button action) you can also easily iterate through states of an enum, check the documentation for the CaseIterable protocol. Often having a property observer (didSet) on the state is a handy place to update other parts of the UI which need to change every time the state changes.

How to allow only one UIImageView to be touched at a time

I have built a simple memory game which consists of 16 UIImageViews.
For the memory game, you are only supposed to be able to touch one card at a time. When you touch the card, it flips over and reveals the image underneath
My issue is that I only want the user to be able to touch one image view at a time. When a user taps on two cards at the same time, it glitches the game. So my question is how do I allow only 1 UIImageView to perform an action at a time, and not allow multiple UIImageViews to perform an action at the same time if touched simultaneously.
Assuming that the user has to unflip a card by selecting it again, I would suggest adding a property to your viewController to keep track of the selectedCard. If there is already a selected card, ignore all others.
var selectedCard: UIImageView?
#objc func handleTap(_ recognizer: UITapGestureRecognizer) {
guard let imageView = recognizer.view as? UIImageView else { return }
if let selected = selectedCard {
if selected === imageView {
// unflip the card
imageView.image = backOfCard
selectedCard = nil
}
} else {
// display face of card
imageView.image = ...
selectedCard = imageView
}
}
Note: Even if a user taps two cards at the same time, handleTap will be called twice in succession. The first card will win and be flipped and become the selectedCard and the second card will be ignored because the if selected === imageView test will fail.
You have a number of choices.
You could put a single tap gesture recognizer on the superview that holds all of your card views and add logic to figure out which one was tapped. Since there is a single method to identify taps, you would't ever get more than one.
Alternately, you could add an instance variable to your class that keeps track of the state, and use it to set userInteractionEnabled to false on the image views that you don't want the user to tap.

Swift the figure of photo changes after retrieve from NSUserDefaults

I want user to choose a photo from album, showing it on one imageView and store it in NSUserDefaults.
The below code means to retrieve this image from NSUserDefaults and show it in headSculptureImage
headSculptureImage.layer.cornerRadius = (headSculptureImage.frame.size.height)/2;
headSculptureImage.layer.masksToBounds = true
headSculptureImage.layer.borderWidth = 0;
This three is used to make this imageView to be a circle
if let userHeadSculpture = NSUserDefaults.standardUserDefaults().objectForKey("userHeadSculpture") {
let image = UIImage(data: userHeadSculpture as! NSData)
headSculptureImage.image = image
headSculptureImage.layer.cornerRadius = (headSculptureImage.frame.size.height)/2;
headSculptureImage.layer.masksToBounds = true
headSculptureImage.layer.borderWidth = 0;
}
The problem is when I choose a pic from album, it works like
what I expected when I reopen app is as same as the pic above, but it showed as
How to fix it?
It appears that you use constraints and use the NSUserDefaults code in viewDidLoad. If that is the case, since viewDidLoad is called before the constraints have loaded, your value of headSculptureImage.frame.size.height is a different one than what you would have with constraints, producing this sort of result.
In order to resolve that, try moving the code to viewDidLayoutSubviews, which is called after the constraints are all set up, to have the cornerRadius value exactly what you need.
Mind that viewDidLayoutSubviews is called quite frequently, so you might want to add some sort of a flag to make sure it is called only when you need it to.

How to detect which image has been tapped in swift

I have created 6 UIImageViews on a ViewController, and I am later going to add TapGestureRecognizers to all of them.
I want to make it so that depending on what image has been clicked, another ViewController will open and display certain information.
For this to happen, I need to know which image has been clicked. How would I do this in Swift?
UIGestureRecognizer has property 'view' this property is the view you add it to. For this example the imageView.
func tap(gesture: UIGestureRecognizer) {
println(gesture.view!.tag) // You can check for their tag and do different things based on tag
}
let img = UIImageView()
img.userInteraction = true
img.tag = 0
img.addGestureRecognizer(UITapGestureRecognizer(self, action: "tap:"))

Resources