I am trying to play a sound file for each image in a collection view, so if the user taps on an image, the user will hear the name of that image. For example, if the user taps on the image of a cat, the user will hear the sound file, "cat". I have created the collection view of images and a UITapGestureRecognizer was added to the cell. The sound file is played in the imageTapped function at the very bottom of the code, but I do not know how to code this. I don't know what to code after: if tap.state == .recognized, let imageView = tap.view as? UIImageView { The current code in that function builds, but I do not hear a sound when I tap each image. I would really appreciate any help.
class FlashcardsViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var animals = ["alligator", "bat", "bear", "beaver", "bird", "butterfly", "camel", "cat", "cheetah", "chicken"]
var bodyparts = ["arm", "ear", "eyes", "foot", "hair", "hand", "head", "leg", "mouth", "nose"]
var classroom = ["backpack", "blackboard", "book", "bookshelf", "calculator", "chair", "chalk", "chalkboard", "clock", "colored pencil"]
var clothes = ["belt", "boots", "coat", "dress", "hat", "jeans", "mittens", "pajamas", "pants", "scarf"]
var family = ["baby", "brother", "dad", "family", "grandma", "grandpa", "grandparents", "mom", "parents", "sister"]
var feelings = ["angry", "cold", "confused", "happy", "hot", "hurt", "sad", "scared", "sick", "tired"]
var food = ["apple", "bacon", "banana", "bean", "blackberry", "blueberry", "broccoli", "butter", "carrot", "cereal"]
var house = ["bathtub", "bed", "bowl", "couch", "cup", "dresser", "fridge", "lamp", "mirror", "plant"]
var transportation = ["ambulance", "bike", "boat", "bus", "car", "firetruck", "helicopter", "motorcycle", "police car", "plane"]
var verbs = ["brush your teeth", "carry", "clap", "color", "cook", "crawl", "cut", "dance", "draw", "drink"]
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var segmentedControl: UISegmentedControl!
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(self.imageTapped(tap:)))
view.addGestureRecognizer(tap)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let arrays = [animals, bodyparts, classroom, clothes, family, feelings, food, house, transportation, verbs]
let sectionArray = arrays[segmentedControl.selectedSegmentIndex]
return sectionArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
let arrays = [animals, bodyparts, classroom, clothes, family, feelings, food, house, transportation, verbs]
cell.imageView?.image = UIImage(named: arrays[segmentedControl.selectedSegmentIndex][indexPath.row])
cell.isUserInteractionEnabled = true
return cell
}
@IBAction func segmentedControlAction(_ sender: Any) {
collectionView.reloadData()
}
func playSound(file: String?) {
if let file = file {
let musicFile = URL(fileURLWithPath: file)
do{
try audioPlayer = AVAudioPlayer(contentsOf: musicFile)
audioPlayer.play()
}catch{
}
}
}
@objc func imageTapped(tap: UITapGestureRecognizer) {
_ = tap.view as? UIImageView
print("imageTapped")
let arrays = [animals, bodyparts, classroom, clothes, family, feelings, food, house, transportation, verbs]
let sectionArray = arrays[segmentedControl.selectedSegmentIndex]
if tap.state == .recognized, let imageView = tap.view as? UIImageView {
for (image) in sectionArray {
imageView.image = UIImage (named: image)
if let sound = Bundle.main.path(forResource: image, ofType: "wav") {
playSound(file: sound)
}
}
}
}
}

I think you are making this more complicated than you need to.
Firstly you keep creating your
arraysmultiple times, there is no need to do this. You could do something like thisThat means in your
cellForItemAtyou do not need to construct it there but you can access thearraysvariable that you just created. For UICollectionView you should useindexPath.iteminstead ofindexPath.row,indexPath.rowis for UITableViews.You also do not need to use a gesture recogniser. UICollectionViews come with a function called
didSelectItemAtthis is called when you tap your cell. So you could do something like this. You may want to check if a file is already playing before you play the next file.Also all those arrays that you are creating initially with the filenames, you should declare them as
letunless you plan on changing the contents of them. It is more performant to useletthanvar.varshould only be used if you plan on changing the value that is stored.So change
to
Checkout Apple's documentation for more information about UICollectionViews https://developer.apple.com/documentation/uikit/uicollectionview