Search code examples
iosarraysswiftxcodeuitapgesturerecognizer

Tap screen for sound(array of sound files), xcode and swift


CURRENTLY - I am in the midst of building a flashcard app. The app displays an array of flash cards which the user can swipe left and right through(code below)As you can see there are 11 different image arrays (each containing a specific group of words)and all of those arrays add up to one final array. I have an audio file to couple each image.

PROBLEM - I want to make it so when the user taps the screen the audio file will play. For example, if the lake image is displaying and the user taps the screen, that lake.mp4 audio file will play, if the user swipes left too the lamb image and taps the screen then the lamb.mp4 audio file will play etc... I know i have to add a tap gesture recognizer but im not sure how to make each audio file couple the correct image.

the code below is what I am currently working with.

import UIKit

class SecondViewController: UIViewController , UIGestureRecognizerDelegate  {

@IBAction func home(_ sender: Any) {
    performSegue(withIdentifier: "home", sender: self)
}

@IBOutlet weak var imgPhoto: UIImageView!

struct List {
    let words: [String]
    var active: Bool
}

let list1 = List(words:["lake", "lamb", "lamp", "lark", "leaf", "leash", "left", "leg", "lime", "lion", "lips", "list", "lock", "log", "look", "love", "lunch"], active: true)

let list2 = List(words: ["ladder", "ladybug", "laughing", "lawnmower", "lemon", "leopard", "leprechaun", "letters", "licking", "lifesaver", "lifting", "lightbulb", "lightning", "listen", "llama"], active: true)

let list3 = List(words: ["alligator", "balance", "ballerina", "balloon", "bowling", "cello", "colors", "curlyhair", "dollar", "dolphin", "elephant", "eyelashes", "gasoline", "goalie", "hula", "jellyfish", "olive", "pillow", "pilot", "polarbear", "rollerskate", "ruler", "silly", "telephone", "television", "tulip", "umbrella", "valentine", "violin", "xylophone", "yellow"], active: true)

let list4 = List(words: ["apple", "ball", "bell", "bubble", "castle", "fall", "fishbowl", "girl", "owl", "pail", "peel", "pool", "smile", "whale", "wheel"], active: true)

let list5 = List(words: ["planet", "plank", "plant", "plate", "play", "plum", "plumber", "plus"], active: true)

let list6 = List(words: ["black", "blanket", "blender", "blocks", "blond", "blood", "blow", "blue"], active: true)

let list7 = List(words: ["flag", "flipflop", "float", "floor", "flower", "fluffy", "flute", "fly"], active: true)

let list8 = List(words: ["glacier", "glad", "glasses", "glide", "glitter", "globe", "glove", "glue"], active: true)

let list9 = List(words: ["clam", "clamp", "clap", "claw", "clean", "climb", "clip", "cloud"], active: true)

let list10 = List(words:["sled", "sleep", "sleeves", "slice", "slide", "slime", "slip", "slow"], active: true)

let list11 = List(words: ["belt", "cold", "dolphin", "elf", "golf", "melt", "milk", "shelf"], active: true)

var imageIndex: Int = 0

var imageList: [String] {

    let wordLists = [list1, list2, list3, list4, list5, list6, list7, list8, list9, list10, list11]



    let active = wordLists.reduce([]) { (result:[String], list:List) in
        if list.active {
            return result + list.words

        } else {
            return result
        }
    }

    return active

}




override func viewDidLoad() {
    super.viewDidLoad()

    imgPhoto.image = UIImage(named: imageList[imageIndex])

    // 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)

}

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 = imageList.count - 1

            }

            imgPhoto.image = UIImage(named: imageList[imageIndex])

        case UISwipeGestureRecognizerDirection.left:
            print("User swiped Left")

            // increase index first

            imageIndex += 1

            // check if index is in range

            if imageIndex > imageList.count - 1 {

                imageIndex = 0

            }

            imgPhoto.image = UIImage(named: imageList[imageIndex])

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

   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)

}

func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{

    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.
        }
    }
}
}

import Foundation; import UIKit; import AVFoundation


class Card: NSObject
{
var image: UIImage
var soundUrl: String
var player: AVAudioPlayer?

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.play()
    print("hhh")
    } catch let error {
        print(error.localizedDescription)
    }
}
}

Solution

  • More Formatted Structure use modeling concept with MMVM architecture

    import AVFoundation
    
            class Card: NSObject 
            {
              var image: UIImage
              var soundUrl: String
              var player: AVAudioPlayer?
    
              init(image: UIImage, soundUrl: String) {
                self.image = image
                self.soundUrl = soundUrl
              }
    
    
            func playSound() 
            {
                guard let url = Bundle.main.url(forResource: self.soundUrl, withExtension: "mp3") 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.play()
                } catch let error {
                    print(error.localizedDescription)
                }
            }
            }
    

    Usage

     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: "lake")!, soundUrl: "lake.mp3"),
            Card(image: UIImage(named: "river")!, soundUrl: "river.mp3"),
            Card(image: UIImage(named: "ocean")!, soundUrl: "ocean.mp3")
            ]
    
    
    
        override func viewDidLoad() {
    
    super.viewDidLoad()
    
    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
    imgPhoto.isUserInteractionEnabled = true
    imgPhoto.addGestureRecognizer(tapGestureRecognizer)
    
    
    
    
            imgPhoto.image = (itemList[0] as! Card).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)
    
        }
    
    
          func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
    {
    
    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 = imageList.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 > imageList.count - 1 {
    
                        imageIndex = 0
    
                    }
    
                    imgPhoto.image = itemList[imageIndex].image
                default:
    
    
                    break //stops the code/codes nothing.
                }
            }
        }
    }
    

    Your last doubt solution

    let firstList:[Card] = [
            Card(image: UIImage(named: "lake")!, soundUrl: "lake"),
            Card(image: UIImage(named: "lamb")!, soundUrl: "lamb"),
            Card(image: UIImage(named: "lamp")!, soundUrl: "lamp")
               ]
    struct List {
        let words: [Card] /*Create array of cards*/
        var active: Bool
    }
    
    let list1 = List(words:firstList, active: true)
    let list2 = List(words:secondList, active: true)
    
     let wordLists = [list1, list2]
    
    print((wordLists[0] as! List).words[0].soundurl)
    
    **OUTPUT**
    lake