Search code examples
iosswiftavfoundationavaudioplayeruitapgesturerecognizer

AVAudioPlayer not playing sound when tap gesture recognizer pressed


I am creating a flashcard app. Right now I am at the point where I can swipe left and right through each image. Each image has a sound file associated with it. When the image is clicked on, the sound file associated with it should play. As of now I can swipe through the images, but no sound plays when i tap the image. Code below.

import UIKit

class SecondViewController: UIViewController , UIGestureRecognizerDelegate  {



var imageIndex: Int = 0
@IBAction func home(_ sender: Any) {
    performSegue(withIdentifier: "home", sender: self)
}

@IBOutlet weak var imgPhoto: UIImageView!


let itemList:[Card] = [
    Card(image: UIImage(named: "alligator")!, soundUrl: "Alligator.m4a"),
    Card(image: UIImage(named: "apple")!, soundUrl: "Apple.m4a"),
    Card(image: UIImage(named: "ball")!, soundUrl: "Ball.m4a")
]



override func viewDidLoad() {
    super.viewDidLoad()


    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
    imgPhoto.isUserInteractionEnabled = true
    imgPhoto.addGestureRecognizer(tapGestureRecognizer)

    imgPhoto.image = (itemList[0] ).image

    // Do any additional setup after loading the view.
    imgPhoto.isUserInteractionEnabled = true

    let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(Swiped(gesture:)))
    leftSwipe.cancelsTouchesInView = false

    let rightSwipe = UISwipeGestureRecognizer(target: self, action: #selector(Swiped(gesture:)))
    rightSwipe.cancelsTouchesInView = false

    leftSwipe.direction = .left
    rightSwipe.direction = .right


    view.addGestureRecognizer(leftSwipe)
    view.addGestureRecognizer(rightSwipe)

}

   @IBAction func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
    print("hhh")
    itemList[imageIndex].playSound()
    // Your action
}

func Swiped(gesture: UIGestureRecognizer) {

    if let swipeGesture = gesture as? UISwipeGestureRecognizer {

        switch swipeGesture.direction {

        case UISwipeGestureRecognizerDirection.right :
            print("User swiped right")

            // decrease index first

            imageIndex -= 1

            // check if index is in range

            if imageIndex < 0 {

                imageIndex = itemList.count - 1

            }

            imgPhoto.image = itemList[imageIndex].image

        case UISwipeGestureRecognizerDirection.left:
            print("User swiped Left")
            // increase index first

            imageIndex += 1

            // check if index is in range

            if imageIndex > itemList.count - 1 {

                imageIndex = 0

            }



            imgPhoto.image = itemList[imageIndex].image
        default:


            break //stops the code/codes nothing.
        }
    }
}
}

Then I have another class which has the AVAudioPlayer code and lays out the definition of each "Card"(code below).

import Foundation; import UIKit; import AVFoundation

var player: AVAudioPlayer?

class Card: NSObject
{
var image: UIImage
var soundUrl: String


init(image: UIImage, soundUrl: String) {
    self.image = image
    self.soundUrl = soundUrl
}
func playSound()
{
    guard let url = Bundle.main.url(forResource: self.soundUrl, withExtension: "m4a") else { return }
    do
    {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try AVAudioSession.sharedInstance().setActive(true)

        player = try AVAudioPlayer(contentsOf: url)
        guard let player = player else { return }
        player.prepareToPlay()
        player.play()
    print("play")
    } catch let error {
        print(error.localizedDescription)
    }
}
}

The code compiles without error, but no sound is played. The program does print a line when I tap the screen but I do not have any line printed from the play sound function which must mean that that part of the code is not being executed. I have put the var player : AVAudioPlayer? outside of the class as recommended but still no luck. I have already added the AVAudioPlayer framework so that is not the problem either.

enter image description here

enter image description here


Solution

  • I think problem is in your extension you have given wrong extension at

     guard let url = Bundle.main.url(forResource: self.soundUrl, withExtension: "m4a")
    

    and also extension not required here

    Card(image: UIImage(named: "alligator")!, soundUrl: "Alligator"),
        Card(image: UIImage(named: "apple")!, soundUrl: "Apple"),
        Card(image: UIImage(named: "ball")!, soundUrl: "Ball")
    

    Change extension with your file extension .mp4