Pressing the button crashes the app

Asked 2 years ago, Updated 2 years ago, 64 views

I make a piano app with Swift.
When I build the app and tap the piano keyboard, it doesn't sound and the app drops.
The source code is as follows:

import UIKit
import AVFoundation

classViewController:UIViewController {
    varpianoSoundC3 = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("C3", ofType:"mp3")!)
    varaudioPlayerC3 = AVAudioPlayer()

    varpianoSoundCS = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("C#", ofType:"mp3")!)
    varaudioPlayerCS=AVAudioPlayer()

    varpianoSoundD = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("D", ofType:"mp3")!)
    varaudioPlayerD=AVAudioPlayer()

    varpianoSoundDS = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("D#", ofType:"mp3")!)
    varaudioPlayerDS=AVAudioPlayer()

    varpianoSoundE=NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("E", ofType:"mp3")!)
    varaudioPlayerE=AVAudioPlayer()

    varpianoSoundF = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("F", ofType:"mp3")!)
    varaudioPlayerF=AVAudioPlayer()

    varpianoSoundFS = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("F#", ofType:"mp3")!)
    varaudioPlayerFS=AVAudioPlayer()

    varpianoSoundG = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("G", ofType:"mp3")!)
    varaudioPlayerG=AVAudioPlayer()

    varpianoSoundGS = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("G#", ofType:"mp3")!)
    varaudioPlayerGS=AVAudioPlayer()

    varpianoSoundA = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("A", ofType:"mp3")!)
    varaudioPlayerA=AVAudioPlayer()

    varpianoSoundAS = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("A#", ofType:"mp3")!)
    varaudioPlayerAS=AVAudioPlayer()

    varpianoSoundB = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("B", ofType:"mp3")!)
    varaudioPlayerB=AVAudioPlayer()

    varpianoSoundC4 = NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("C4", ofType:"mp3")!)
    varaudioPlayerC4 = AVAudioPlayer()

    override func viewDidLoad(){
        super.viewDidLoad()

        let audioPlayerC3 = try!AVAudioPlayer (contentsOfURL:pianoSoundC3)
        audioPlayerC3.prepareToPlay()

        let audioPlayerCS=try!AVAudioPlayer (contentsOfURL:pianoSoundCS)
        audioPlayerCS.prepareToPlay()

        let audioPlayerD=try!AVAudioPlayer (contentsOfURL:pianoSoundD)
        audioPlayerD.prepareToPlay()

        let audioPlayerDS=try!AVAudioPlayer (contentsOfURL:pianoSoundDS)
        audioPlayerDS.prepareToPlay()

        let audioPlayerE=try!AVAudioPlayer (contentsOfURL:pianoSoundE)
        audioPlayerE.prepareToPlay()

        let audioPlayerF=try!AVAudioPlayer (contentsOfURL:pianoSoundF)
        audioPlayerF.prepareToPlay()

        let audioPlayerFS=try!AVAudioPlayer (contentsOfURL:pianoSoundFS)
        audioPlayerFS.prepareToPlay()

        let audioPlayerG=try!AVAudioPlayer (contentsOfURL:pianoSoundG)
        audioPlayerG.prepareToPlay()

        let audioPlayerGS=try!AVAudioPlayer (contentsOfURL:pianoSoundGS)
        audioPlayerGS.prepareToPlay()

        let audioPlayerA=try!AVAudioPlayer (contentsOfURL:pianoSoundA)
        audioPlayerA.prepareToPlay()

        let audioPlayerAS=try!AVAudioPlayer (contentsOfURL:pianoSoundAS)
        audioPlayerAS.prepareToPlay()

        let audioPlayerB=try!AVAudioPlayer(contentsOfURL:pianoSoundB)
        audioPlayerB.prepareToPlay()

        let audioPlayerC4=try!AVAudioPlayer(contentsOfURL:pianoSoundC4)
        audioPlayerC4.prepareToPlay()
    }

    override funcdidReceiveMemoryWarning(){
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @ IBAction func C3 (sender: UIButton) {
        audioPlayerC3.play()
    }
    @ IBAction func CS (sender: UIButton) {
        audioPlayerCS.play()
    }

    @ IBAction func D (sender: UIButton) {
         audioPlayerD.play()
    }

    @ IBAction func DS (sender: UIButton) {
         audioPlayerDS.play()
    }
    @ IBAction func E (sender: UIButton) {
        audioPlayerE.play()
    }

    @ IBAction funcF (sender: UIButton) {
        audioPlayerF.play()
    }

    @ IBAction funcFS (sender: UIButton) {
        audioPlayerFS.play()
    }

    @ IBAction func G (sender: UIButton) {
        audioPlayerG.play()
    }

    @ IBAction func GS (sender: UIButton) {
        audioPlayerGS.play()
    }

    @ IBAction func A (sender: UIButton) {
        audioPlayerA.play()
    }

    @ IBAction func AS (sender: UIButton) {
        audioPlayerAS.play()
    }

    @ IBAction func B (sender: UIButton) {
        audioPlayerB.play()
    }

    @ IBAction func C4 (sender: UIButton) {
        audioPlayerC4.play()
    }
}

swift xcode iphone

2022-09-30 10:14

1 Answers

There are some bad statements in your code.

First, just below the class, the declaration part of the properties.

varaudioPlayerC3=AVAudioPlayer()

(All other audioPlayerXXs are no good as well.)
AVAudioPlayer() means that you are creating an instance of the AVAudioPlayer class. The reference for the AVAudioPlayer class does not mention an argumentless constructor, but when I try, the application always crashes.Why bother generating and substituting these useless instances?

The more unused instances you create, the more heaps you waste.ARC frees up the area itself when you replace it with a real instance, but acquiring and releasing heap is a very expensive process, so keep in mind that do not generate useless instances as much as possible.

If viewDidLoad() sets the actual value to be used, such as your code, the declaration part of the property should be written as follows:

varaudioPlayerC3:AVAudioPlayer!

In the viewDidLoad(), you made this declaration.

let audioPlayerC3=try!AVAudioPlayer(contentsOfURL:pianoSoundC3)

If you write a variable declaration in an execution block, such as let or var, you have declared a valid local variable (constant) only within that block.Even if the variable names are the same, they are completely different from the properties.

In other words, the audioPlayerC3 in viewDidLoad() is completely different from the audioPlayerC3 property, and when viewDidLoad() is executed, the variable disappears and the instance is released.As a result, the audioPlayerC3 in the properties referenced later in the C3(_:) method still contains the instance from the uselessness mentioned above, so the application crashes because you call the play() method.

If you write the following, it will be substituted for properties instead of declaring local variables.

self.audioPlayerC3=try!AVAudioPlayer(contentsOfURL:pianoSoundC3)

(self. is not required in this case, but it is recommended to distinguish properties from local variables by always preferring self. to instance properties until you get used to it.) Of course, modify all other let audioPlayer... as well.

There may be something else that doesn't work properly, but if you still can't, please ask again, including more detailed information as stated in the comments.


2022-09-30 10:14

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.