1

This is a simple Xylophone app from a tutorial that i am following. If we press on each button, a new note is played. It works fine. But when i want to swipe from 1 button to another, there is no sound.

Github link for the complete project: https://github.com/jaineelesh/Xylophone

i have tried with the Touch Drag Enter/Exit/Inside/Outside also, but nothing seems to work for me.

Please help.

ViewController.swift file

import UIKit
import AVFoundation

class ViewController: UIViewController{

var player: AVAudioPlayer?

override func viewDidLoad() {
    super.viewDidLoad()
}

@IBAction func noteOnDrag(_ sender: UIButton) {
    // selecting the correct note based on the tag
    //playSound(tag: sender.tag)
    print("enter")
}

@IBAction func noteOnDragExit(_ sender: UIButton) {
    print("Exit")
}

@IBAction func notePressed(_ sender: UIButton) {
    // selecting the correct note based on the tag
    //playSound(tag: sender.tag)
}

func playSound(tag: Int) {
    let note = "note" + String(tag)
    guard let url = Bundle.main.url(forResource: note, withExtension: "wav") else { return }

    do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try AVAudioSession.sharedInstance().setActive(true)

        player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.wav.rawValue)

        guard let player = player else { return }

        player.play()
    } catch let error {
        print(error.localizedDescription)
    }
}

And this is how the app looks. enter image description here

I am a beginner so my knowledge is very limited. I tried to find the solutions but there are none which explains how to solve my problem with swift 4. If there exists some old solution, then i am not able to understand them. i tried to use the below events but they don't seem to work. enter image description here

  • You might be better off doing these with UIControls and not with UIButtons. It might be a bit more difficult to set them up, as it would be through the storyboard, but making a custom UIControl class and placing them on your view controller might be a cleaner solution. They have a draggedInto method that will fire and you can pass that back to your view controller so as to play the sound that you want to play. – Alan S Sep 04 '18 at 12:53
  • From a musical point of view, the functionality you are looking for and have described is called a “glissando” (swiping or dragging from one button/key to the next. It might be worth looking up “How to Glissando” in code/programming/swift etc. I am also trying to add some functionality: 1) playChords (e.g. four fingers, four taps, four notes at once. Four mediaPlayer instances (create and release, re-using four media player instances) 2) noteNames toggle on and off (e.g. IB boolean switch true/false for button.text) If you have any luck or ideas for this, do let me know. Best wishes, Tony Urba – UrbanSmash Sep 03 '19 at 23:13

1 Answers1

1

You have connected event Touch Up Inside thats why pressing works (your notePressed function). If you want your code to work also with swiping then try connecting Touch Drag Exit or Touch Drag Enter events.

On your last screen select that event and drag it onto

@IBAction func notePressed(_ sender: UIButton) {
    // selecting the correct note based on the tag
    //playSound(tag: sender.tag)
}

Events names are self-describing but here you can also find explanation

//EDIT: Ok, I probably did not understand you at first. I think that your problem is similar to THIS.

The idea:

  1. Make an outlet collection that contains all your buttons.

    @IBOutlet var buttons: [UIButton]!
    
  2. Use touchesMoved method (example):

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
        guard let touch = event?.allTouches?.first else {return}
        let touchLocation = touch.location(in: self.view)
        buttons.forEach { (button) in
            if button.frame.contains(touchLocation) {
                print(button.tag)
            }
        }
    }
    
gorzki
  • 433
  • 3
  • 10
  • already did that with the drag enter/exit action events. but nothing happens. I used a print() statement but it never gets called when i swipe from 1 button to other. –  Sep 03 '18 at 10:17
  • Hi helps but very slightly and doesn't do what exactly i am looking for. Few Issues that i am facing with your above solution: 1. It only works when i swipe from outside the button to the button. Doesn't work if i swipe from 1 button to button. 2. even while i am moving inside the button, the note keeps on playing, But that is contrary to the idea of a xylophone key press because, if a key is pressed, there should 1 sound till i release the button. But here when i even move inside the button, it give new sound. –  Sep 04 '18 at 05:29