2017-08-26 105 views
0

我正在研究一個應用程序(鋼琴),它有一系列按鈕,每個按鈕都有不同的mp3。屏幕上會顯示12個按鈕(鋼琴鍵),我希望用戶能夠播放單個聲音或在一對情侶間輕掃以聽到多個聲音。就像一架真正的鋼琴。我見過很多應用程序這樣做,但當用戶快速滑過多個按鈕時,我的問題似乎有問題。以相同的速度,其他應用程序將播放所有的音符,但我的音樂將跳過一些。感謝您的任何幫助!這將使我的應用程序有所不同!滑過鋼琴鍵(swift/iOS)

一對夫婦有關此代碼的快速註解:

-I只是這裏有裸露的骨頭,以節省空間

-I只顯示6個音頻播放器,但你的想法

-The locationInNote1 ... Note2 ... Note3只顯示6這裏保存位置,但你的想法

- 按鈕動作中的「note1」是一個字符串,可以在用戶選擇不同的八度音來自,但它只是一個#,所以音頻文件超imately是1.mp3,2.mp3等

- 按鈕動作playNote1是相同的其他按鈕動作,所以我沒有在那裏重複他們。

var audioPlayer = AVAudioPlayer() 
var audioPlayer2 = AVAudioPlayer() 
var audioPlayer3 = AVAudioPlayer() 
var audioPlayer4 = AVAudioPlayer() 
var audioPlayer5 = AVAudioPlayer() 
var audioPlayer6 = AVAudioPlayer() 

func playNote(for locationInView: CGPoint) { 
    let locationInNote1 = note1Button.convert(locationInView, from: view) 
    let locationInNote2 = note2Button.convert(locationInView, from: view) 
    let locationInNote3 = note3Button.convert(locationInView, from: view) 
    let locationInNote4 = note4Button.convert(locationInView, from: view) 
    let locationInNote5 = note5Button.convert(locationInView, from: view) 
    let locationInNote6 = note6Button.convert(locationInView, from: view) 

    if note1Button.point(inside: locationInButton1, with: nil) { 
     playNote1(self) 
    } 

    if note2Button.point(inside: locationInButton2, with: nil) { 
     playNote2(self) 
    } 

    if note3Button.point(inside: locationInButton3, with: nil) { 
     playNote3(self) 
    } 

    if note4Button.point(inside: locationInButton4, with: nil) { 
     playNote4(self) 
    } 

    if note5Button.point(inside: locationInButton5, with: nil) { 
     playNote5(self) 
    } 

    if note6Button.point(inside: locationInButton6, with: nil) { 
     playNote6(self) 
    } 
} 

@IBAction func playNote1(_ sender: Any) { 
    let note1mp3 = note1 
     if let path = Bundle.main.path(forResource: note1mp3, ofType: "mp3") { 
      let url = URL(fileURLWithPath: path) 
      do { 
       audioPlayer = try AVAudioPlayer(contentsOf: url) 
       audioPlayer.prepareToPlay() 
       audioPlayer.play() 
      } 
      catch { 
       print(error) 
      }  
     } 
} 

override func viewDidLoad() { 
    super.viewDidLoad() 

    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) 
    view.addGestureRecognizer(panGesture) 
+0

僅供參考 - 在'playNote'方法中使用'if/else',因爲一個點一次只能在一個按鈕中。 – rmaddy

+0

爲什麼從音樂包中加載每首mp3,並且每次應該播放音符時都會反覆創建新的音頻播放器?這是非常低效的。 – rmaddy

+0

爲什麼有6個重複的'playNoteX'方法?只要有一個,並傳遞音符編號,以便可以訪問正確的mp3文件。 – rmaddy

回答

0

這裏是一個辦法希望:

  • 提高代碼
  • 簡化程式碼
  • 解決您遇到

在這個例子中的問題,我只會放3個音頻播放器。 我會盡力讓它直線前進儘可能...

import UIKit 

class MyViewController: UIViewController { 
    var audioPlayer = AVAudioPlayer() 
    var audioPlayer2 = AVAudioPlayer() 
    var audioPlayer3 = AVAudioPlayer() 
    @IBOutlet var notes: [UIButton]! 
    let references = [note1, note2, note3] 

    @IBAction func notePressed(_ sender: UIButton) { 
     play(note: notes.index(of: sender)! + 1) 
    } 

    func play(note: Int) { 
     let reference = references[note - 1] 
     if let path = Bundle.main.path(forResource: reference, ofType: "mp3") {  
      let url = URL(fileURLWithPath: path) 
      do { 
       audioPlayer = try AVAudioPlayer(contentsOf: url) 
       audioPlayer.prepareToPlay() 
       audioPlayer.play() 
      } 
      catch { 
       print(error) 
      } 
     } 
    } 
} 

說明

@IBOutlet VAR注意事項:的UIButton]!
這是一個插座收集的按鈕。要做到這一點,連接一個按鈕,但選擇插座收集而不是隻是插座。確保你按順序連接每個按鈕(1,2,3),否則會中斷!

讓引用= [注1,注2,注3]
這是到每個音符的文件的引用的數組。這樣我們只需要一個功能就可以播放音符。

@IBAction FUNC notePressed(_:發件人:)
此功能得到由按鈕調用。對於每個按鈕,連接觸摸拖動輸入(用於滑動筆記)和觸摸下來操作。如果你願意,你可以添加其他的。該功能比較發件人筆記奧特萊斯收集找出哪些筆記被按下,然後傳遞給func play(:note :)函數。

FUNC播放(:注意:)
該函數將音符編號,並播放相應的文件。它幾乎與原來的一樣,但不是固定音符,而是有一個由@IBAction func notePressed(_:sender :)方法傳遞的音符。

我希望這是有益的,祝你好運!