I am relatively new to Swift.
I have many images (though right now I am testing with four) which I am trying to hide (temporarily to make sure the foundational code is working, instead I really want to insert an image under the tapped image) when they are tapped.
I have created an array of ImageViews which I plan to expand once I have working code. I tried to add UITapGestureRecognizers to each ImageView using a for loop in addGestures() and then have selectImage() hide the tapped ImageView. The code compiles without error, but fails with uncaught NSException when one of these images is tapped. Any tips on how to do this effectively without too much manual coding for each image?
Code attached
Please check below code
func addGestureRecognizer(){
for imageView in imageArray{
imageView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(gesture:)))
imageView.addGestureRecognizer(tap)
}
}
#objc func handleTap(gesture:UITapGestureRecognizer){
let imageView = gesture.view
imageView?.isHidden = true
}
in your code you're passing imageView instead of gesture on selector.however you can get imageView by gesture.view.
Also there is no need for separate function for enable userInteraction.
Here is what you can try
class GestureStackVC: UIViewController {
/// Image Outlets
#IBOutlet weak var img1: UIImageView!
#IBOutlet weak var img2: UIImageView!
#IBOutlet weak var img3: UIImageView!
/// ImageView Array
var imagesArray : [UIImageView]?
/// Image Gesture
var imageTapGesture : UITapGestureRecognizer?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
/// Allocate Array
imagesArray = [UIImageView]()
/// Add Required Values
imagesArray = [img1,img2,img3]
/// Add gesture
for imageView in imagesArray!{
let tap = UITapGestureRecognizer(target: self, action: #selector(imageTapHandler(_:)))
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(tap)
}
}
/// tap Handler
#objc func imageTapHandler(_ sender: UITapGestureRecognizer) {
/// Hide the Sender View
sender.view?.isHidden = true
/// Done
}
}
First Output with 3 Images
Output when clicked On first ImageView1 - Results its hidden
Output when clicked On first ImageView2 - Results its hidden
Related
I have a custom view with stackview inside. In my stack view contains Image, Label1, and Label2 horizontally.
I set my custom view with constraints with height = 25 and width = 160.
I need to tap only on a specific part of the view. How can I do it?
For example, only Label2 can be clickable.
#IBOutlet weak var label2: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let gesture = UITapGestureRecognizer(target: self, action: #selector(click))
label2.isUserInteractionEnabled = true
label2.addGestureRecognizer(gesture)
}
#objc func click(sender:UITapGestureRecognizer) {
}
You might want to use GestureRecognizers https://developer.apple.com/documentation/uikit/touches_presses_and_gestures
I am learning Swift, and I am throwing myself in the deep end to force myself to learn the language. I have a nephew who is a baby and thought to make an app to help him learn numbers.
The app is designed to set a set number of buttons on the screen like the one provided below. I have the code to play Directions, which tells the user which number to select. A-N14a, the audio file, says to click the 4. The Done button is set to move to the next screen.
What I am asking is that if I want 4 to be pressed, and they press the 9, I want to know how to implement a feature to give a hint to click the number 4? The idea is to change the background to a button, but I don't know how to implement the feature. I am also open to other ideas. As a note, I do not know what to do, and I'm trying to learn, so the code provided is probably very simplistic and is at the beginning stages.
Below is an image of the screen and the code for that page.
ScreenShot of Page
import UIKit
import AVFoundation
class Intervention_Numerals1: UIViewController {
#IBOutlet weak var Directions: UIButton!
#IBOutlet weak var Done: UIButton!
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
setUpElements()
//Audio Test
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "A-N14a", ofType:"mp3")!))
audioPlayer.prepareToPlay()
} catch {
print(error)
}
}
func setUpElements() {
// Style the elements
Utilities.styleFilledButton(Directions)
Utilities.styleFilledButton(Done)
}
#IBAction func Play(_ sender: Any) {
audioPlayer.play()
}
}
Please let me know any tips or advice or links to similar questions, even though I could not find any on my own.
Here's what I would do:
Record the sound "Tap the number" and then the sounds for the numbers 0 through 9. Name the number sounds "0.mp3" through "9.mp3"
Create a storyboard with 4 buttons on it (like the picture you posted.)
Set up button IBOutlets buttonA - buttonD. Put those buttons into an array:
let buttonsArray = [buttonA, buttonB, buttonC, buttonD]
Fill an array with the numbers 0-9. Shuffle it. Remove 4 values put them into an array "buttonValues" (use the method removeLast().) The code to generate non-repeating values from 0-9 might look like this:
var randomNumbers = [Int]() //Define an array to hold random Ints
var lastValueReturned: Int?
//Function to return a random Int. It won't return the same value twice
func randomNumber() -> Int {
//Remove and return an item from the array
var result: Int
repeat {
//If the array is empty, fill it with the shuffled numbers 0...9
if randomNumbers.isEmpty {
randomNumbers += Array(0...9).shuffled()
}
result = randomNumbers.removeLast()
} while result == lastValueReturned
lastValueReturned = result
return result
}
Loop through your array of buttonValues and install the string for each number as the title of one of your buttons:
for index = 0...3 {
buttonsArray[index].setTitle("(buttonValues[index])", forSate: .normal)
}
Pick an index 0-3 to be the "correct" number.
let indexToPick = Int.random(in: 0...3)
Look up that value in buttonValues, and use it to pick a sound file to play:
let numberToPick = buttonValues[indexToPick]
let soundName = "\(numberToPick).mp3"
Load and play the "tap the number" sound, and then Load and play the sound for the selected number (soundName).
When the user taps a button, have the IBAction method use the sender parameter that is passed to it, and look in the array of buttons, buttonsArray, to see which button index was tapped.
If it is the correct button, take the success action.
If the tapped button index is not indexToPick, do an animation that changes the background color of the button at indexToPick, or the button's border width, or something, and then animates it back to normal. (Look at the UIView animate(duration:) family of methods for how to animate the button's background color. Use the form that takes an options: parameter, and set the .autoreverse option.)
If you're a newbie to iOS development, figuring out how to animate your correct answer button could be a challenge. I created a sample project that just animates one of 4 random buttons: https://github.com/DuncanMC/ButtonAnimation.git
The code for that project is as follows:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var buttonA: UIButton!
#IBOutlet weak var buttonB: UIButton!
#IBOutlet weak var buttonC: UIButton!
#IBOutlet weak var buttonD: UIButton!
//Define an empty array to hold buttons.
var buttonsArray = [UIButton]()
override func viewDidLoad() {
super.viewDidLoad()
//Put our button outlets into an array so we can reference them by index.
buttonsArray = [buttonA, buttonB, buttonC, buttonD]
//Give our buttons a cornerRadius so they look rounded when we add a border and fill color
for button in buttonsArray {
button.layer.cornerRadius = 10
}
}
#IBAction func handleAnimateButton(_ sender: UIButton) {
sender.isEnabled = false
//Pick a random button
let button = buttonsArray.randomElement()!
//Create an auto-reversing animation that fills the button with cyan, and draws a border around it.
//(Showing the border won't fade in and out, but it doesn't really matter)
UIView.animate(withDuration: 0.25,
delay: 0,
options: [.autoreverse, .curveEaseInOut],
animations: {
button.backgroundColor = .cyan
button.layer.borderWidth = 1.0
}, completion: {
success in
button.backgroundColor = .clear
sender.isEnabled = true
button.layer.borderWidth = 0
})
}
}
I would do as follows:
1. Create as many IBOutlets as your numbers (I suppose 0-9 for your example?) and link them to your buttons - E.g.
#IBOutlet weak var Button1: UIButton!
#IBOutlet weak var Button2: UIButton!
// Create as many as you need - Probably 10?
2. Create an IBAction and link it to all your buttons, with this code
#IBAction func checkCorrectAnswer(_ sender: UIButton) {
let arrayOfButtons:[UIButton] = [Button1, Button2] // Here you add all your buttons
let buttonTitle = sender.title(for: .normal)!
if buttonTitle == "YOUR CORRECT ANSWER" { //You have to substitute "YOUR CORRECT ANSWER" with the right string value
sender.backgroundColor = .green
} else {
sender.backgroundColor = .red
for i in arrayOfButtons {
if i.titleLabel?.text == "YOUR CORRECT ANSWER" { i.backgroundColor = .orange }
}
}
}
Enjoy!
I am trying to display a new image based on a user tapping the image view. I have added a UITapGestureRecognizer on top of the UIImageView which has been defined a "displayPhoto" and connected it as an outlet to the view controller.
#IBOutlet weak var displayPhoto: UIImageView!
#IBAction func changeImage(_ sender: UITapGestureRecognizer) {
displayPhoto.image = UIImage(named: "myimage")
}
The sent action is listed as follows:
sent actions
When I run the app and click on the image, nothing happens. I've even tried to make the first line of the IBAction function a fatal error but nothing happens. What am I missing?
Thanks in advance for any help.
The full view and connection
Tap Gesture Recognizer Window
Firstly you try; clean your project
command+option+shift+K
The first case cannot be empty
You should add a picture.
override func viewDidLoad() {
super.viewDidLoad()
displayPhoto.image = UIImage(named: "firsCase")
}
I am displaying a custom UIView. There is a variable 'hideLogo' which when set to false should hide the Logo image when the view appears. However the logo is only hidden once the subview is re-added.
How can I make the image hidden when the view is added first time.
class MenuBar: UIView {
#IBOutlet var LogoImage: UIImageView!
static var showLogo: Bool?
override func awakeFromNib() {
super.awakeFromNib()
if(MenuBar.showLogo == false){
self.LogoImage.isHidden = true
}
}
subview instantiated from another class:
MenuBar.showLogo = false
self.view.insertSubview(messageView.create(viewController: self), belowSubview: view.viewWithTag(1)!)
The problem is that you are setting showLogo but you are not responding to that by setting the logo image's isHidden to true. And it's going to be hard for you to do that so long as showLogo is a static property. Make it an instance property and now you can give it a setter observer.
I have a UIButton inside my cell together with an image and a text label. I manage to change the image and label programatically, but the UIButton does not seem to respond to anything except isHidden.
This is my code, the button that is not changing is followButton:
import UIKit
class ProfileTableCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var profileImage: UIImageView!
#IBOutlet weak var followButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
self.profileImage.layer.borderWidth = 0.0;
self.profileImage.layer.cornerRadius = self.profileImage.frame.size.width/2;
self.profileImage.clipsToBounds = true
self.profileImage.image = UIImage(named: "belt")
self.name.text = "Bar Refaeli"
self.followButton.layer.borderColor = UIColor.black.cgColor
self.followButton.layer.borderWidth = 3.0;
self.followButton.layer.cornerRadius = self.frame.size.width/4
self.followButton.backgroundColor = UIColor.black
}
func setCell(image: UIImage, name: String){
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
The profileImage and name outlets change the appearance fine, like mentioned above.
I also tried to remove the button and bring it back in, clean xcode project, remove the outlet reference and connecting it again. Pretty frustrated by now.
I also tried to change the background color of the button through the storyboard, just for testing, and it does not change it! what does change is the titleLabel and the text color.
awakeFromNib()- Prepares the receiver for service after it has been loaded from an Interface Builder archive, or nib file.
Given that, move your code to a view initiating method like viewDidLoad or viewDidAppear(_:)
Child objects that are attributes like textLabels act differently than child view objects.
Eventually I actually solved this by tossing the table view to the garbage and implementing the same needs using a collection view. there was no problem there..