I'm making my first app in Swift: a Piano app. I'd like to get your feedback especially about how I can make codes shorter. I maybe have to use arrays and loops and something, and searched by myself but couldn't get it.
view controller.swift
import UIKit
import AVFoundation
class ViewController: UIViewController {
var pianoSoundC3 = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("C3", ofType: "mp3")!)
var audioPlayerC3 = AVAudioPlayer()
var pianoSoundCS = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("C#", ofType: "mp3")!)
var audioPlayerCS = AVAudioPlayer()
var pianoSoundD = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("D", ofType: "mp3")!)
var audioPlayerD = AVAudioPlayer()
var pianoSoundDS = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("D#", ofType: "mp3")!)
var audioPlayerDS = AVAudioPlayer()
var pianoSoundE = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("E", ofType: "mp3")!)
var audioPlayerE = AVAudioPlayer()
var pianoSoundF = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("F", ofType: "mp3")!)
var audioPlayerF = AVAudioPlayer()
var pianoSoundFS = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("F#", ofType: "mp3")!)
var audioPlayerFS = AVAudioPlayer()
var pianoSoundG = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("G", ofType: "mp3")!)
var audioPlayerG = AVAudioPlayer()
var pianoSoundGS = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("G#", ofType: "mp3")!)
var audioPlayerGS = AVAudioPlayer()
var pianoSoundA = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("A", ofType: "mp3")!)
var audioPlayerA = AVAudioPlayer()
var pianoSoundAS = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("A#", ofType: "mp3")!)
var audioPlayerAS = AVAudioPlayer()
var pianoSoundB = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("B", ofType: "mp3")!)
var audioPlayerB = AVAudioPlayer()
var pianoSoundC4 = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("C4", ofType: "mp3")!)
var audioPlayerC4 = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
audioPlayerC3 = AVAudioPlayer(contentsOfURL: pianoSoundC3, error: nil)
audioPlayerC3.prepareToPlay()
audioPlayerCS = AVAudioPlayer(contentsOfURL: pianoSoundCS, error: nil)
audioPlayerCS.prepareToPlay()
audioPlayerD = AVAudioPlayer(contentsOfURL: pianoSoundD, error: nil)
audioPlayerD.prepareToPlay()
audioPlayerDS = AVAudioPlayer(contentsOfURL: pianoSoundDS, error: nil)
audioPlayerDS.prepareToPlay()
audioPlayerE = AVAudioPlayer(contentsOfURL: pianoSoundE, error: nil)
audioPlayerE.prepareToPlay()
audioPlayerF = AVAudioPlayer(contentsOfURL: pianoSoundF, error: nil)
audioPlayerF.prepareToPlay()
audioPlayerFS = AVAudioPlayer(contentsOfURL: pianoSoundFS, error: nil)
audioPlayerFS.prepareToPlay()
audioPlayerG = AVAudioPlayer(contentsOfURL: pianoSoundG, error: nil)
audioPlayerG.prepareToPlay()
audioPlayerGS = AVAudioPlayer(contentsOfURL: pianoSoundGS, error: nil)
audioPlayerGS.prepareToPlay()
audioPlayerA = AVAudioPlayer(contentsOfURL: pianoSoundA, error: nil)
audioPlayerA.prepareToPlay()
audioPlayerAS = AVAudioPlayer(contentsOfURL: pianoSoundAS, error: nil)
audioPlayerAS.prepareToPlay()
audioPlayerB = AVAudioPlayer(contentsOfURL: pianoSoundB, error: nil)
audioPlayerB.prepareToPlay()
audioPlayerC4 = AVAudioPlayer(contentsOfURL: pianoSoundC4, error: nil)
audioPlayerC4.prepareToPlay()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func C3(sender: UIButton) {
audioPlayerC3.currentTime = 0
audioPlayerC3.play()
}
@IBAction func CS(sender: UIButton) {
audioPlayerCS.currentTime = 0
audioPlayerCS.play()
}
@IBAction func D(sender: UIButton) {
audioPlayerD.currentTime = 0
audioPlayerD.play()
}
@IBAction func DS(sender: UIButton) {
audioPlayerDS.currentTime = 0
audioPlayerDS.play()
}
@IBAction func E(sender: UIButton) {
audioPlayerE.currentTime = 0
audioPlayerE.play()
}
@IBAction func F(sender: UIButton) {
audioPlayerF.currentTime = 0
audioPlayerF.play()
}
@IBAction func FS(sender: UIButton) {
audioPlayerFS.currentTime = 0
audioPlayerFS.play()
}
@IBAction func G(sender: UIButton) {
audioPlayerG.currentTime = 0
audioPlayerG.play()
}
@IBAction func GS(sender: UIButton) {
audioPlayerGS.currentTime = 0
audioPlayerGS.play()
}
@IBAction func A(sender: UIButton) {
audioPlayerA.currentTime = 0
audioPlayerA.play()
}
@IBAction func AS(sender: UIButton) {
audioPlayerAS.currentTime = 0
audioPlayerAS.play()
}
@IBAction func B(sender: UIButton) {
audioPlayerB.currentTime = 0
audioPlayerB.play()
}
@IBAction func C4(sender: UIButton) {
audioPlayerC4.currentTime = 0
audioPlayerC4.play()
}
}
-
\$\begingroup\$ It's worth nothing that if you can penetrate the documentation, Apple actually provides AUSampler, which can load a custom set of samples into a MIDI instrument. It's basically designed to do exactly what you're doing here, only it uses a preprepared bundle of samples, loads in one step, and then you can fire MIDI commands at it rather than working a whole bunch of AVAudioPlayers. \$\endgroup\$Matt Gibson– Matt Gibson2014年12月15日 08:48:59 +00:00Commented Dec 15, 2014 at 8:48
1 Answer 1
I think this should work. The key (pun intended) to making this work is to take advantage of the tag
property of UIButton
. In Interface Builder, set a different tag to each piano key. Start with 0
for "C3"
, 1
for "C#"
, up to 12
for "C4"
. Wire all of those keys to playKey
.
import UIKit
import AVFoundation
class ViewController: UIViewController {
let pianoKeys = ["C3", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "C4"]
var audioPlayers:[AVAudioPlayer] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for key in pianoKeys {
let pianoSoundURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(key, ofType: "mp3")
let audioPlayer = AVAudioPlayer(contentsOfURL: pianoSoundURL, error: nil)
audioPlayer.prepareToPlay()
audioPlayers.append(audioPlayer)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func playKey(sender: UIButton) {
let keynum = sender.tag
audioPlayers[keynum].currentTime = 0
audioPlayers[keynum].play()
}
}
-
\$\begingroup\$ It worked! now I come to understand Arrays, for in, and .tag property. Thank you very much! \$\endgroup\$Bick– Bick2014年10月06日 04:52:22 +00:00Commented Oct 6, 2014 at 4:52