Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

swift: audio slider control

Problem:

When I segue to the viewcontroller that holds the buttons and slider it crashes the app and gives me Thread 1:EXC_BAD_ACCESS (code=1, address=0x38) on the line of slider.maximumValue = Float(audioPlayer.duration). In the viewcontroller I have a play/pause button, a stop button, and a slider that controls where the audio plays.

Code:

import UIKit
import AVFoundation

class AgnesAudioViewController: UIViewController {

var audioPlayer = AVAudioPlayer()
var toggleState = 1
@IBOutlet var slider: UISlider!

@IBAction func done(sender: AnyObject) {
    dismissViewControllerAnimated(true, completion: nil)
}

@IBAction func play(sender: AnyObject) {
    audioPlayer.play()
}

@IBAction func pause(sender: AnyObject) {
    audioPlayer.pause()
}

@IBAction func stop(sender: AnyObject) {
    audioPlayer.stop()
}

@IBAction func scrubAudio(sender: AnyObject) {
    audioPlayer.stop()
    audioPlayer.currentTime = NSTimeInterval(slider.value)
    audioPlayer.prepareToPlay()
    audioPlayer.play()
}

@IBAction func playPauseButton(sender: AnyObject) {
    var playBtn = sender as! UIButton
    if toggleState == 1 {
        audioPlayer.play()
        toggleState = 2
        playBtn.setImage(UIImage(named:"pause.png"),forState:UIControlState.Normal)
    } else {
        audioPlayer.pause()
        toggleState = 1
        playBtn.setImage(UIImage(named:"play.png"),forState:UIControlState.Normal)
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    var timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("updateSlider"), userInfo: nil, repeats: true)

    slider.maximumValue = Float(audioPlayer.duration)

    let pathString = NSBundle.mainBundle().pathForResource("agnes", ofType: "mp2")

    if let pathString = pathString {

        let pathURL = NSURL(fileURLWithPath: pathString)

        do {

            try audioPlayer = AVAudioPlayer(contentsOfURL: pathURL)

        } catch {

            print("error")
        }


    }

}

func updateSlider() {
    slider.value = Float(audioPlayer.currentTime)
}
}
like image 978
Hunter Avatar asked Dec 24 '22 10:12

Hunter


2 Answers

This fixed the problem:

import UIKit
import AVFoundation

class AgnesAudioViewController: UIViewController {

var audioPlayer = AVAudioPlayer()
var toggleState = 1
@IBOutlet var slider: UISlider!
@IBOutlet var playedTime: UILabel!

@IBAction func done(sender: AnyObject) {
    dismissViewControllerAnimated(true, completion: nil)
    audioPlayer.stop()
}

@IBAction func play(sender: AnyObject) {
    audioPlayer.play()
    updateTime()
}

@IBAction func pause(sender: AnyObject) {
    audioPlayer.pause()
    updateTime()
}

@IBAction func stop(sender: AnyObject) {
    audioPlayer.stop()
    updateTime()
}

@IBAction func scrubAudio(sender: AnyObject) {
    audioPlayer.stop()
    audioPlayer.currentTime = NSTimeInterval(slider.value)
    audioPlayer.prepareToPlay()
    audioPlayer.play()
}

func updateTime() {
    var currentTime = Int(audioPlayer.currentTime)
    var duration = Int(audioPlayer.duration)
    var total = currentTime - duration
    var totalString = String(total)

    var minutes = currentTime/60
    var seconds = currentTime - minutes / 60

    playedTime.text = NSString(format: "%02d:%02d", minutes,seconds) as String
}

@IBAction func playPauseButton(sender: AnyObject) {
    //1 = play
    //2 = pausw
    var playBtn = sender as! UIButton
    if toggleState == 1 {
        audioPlayer.play()
        toggleState = 2
        playBtn.setImage(UIImage(named:"pause2.png"),forState:UIControlState.Normal)
    } else {
        audioPlayer.pause()
        toggleState = 1
        playBtn.setImage(UIImage(named:"play2.png"),forState:UIControlState.Normal)
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    var updateTimer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("updateTime"), userInfo: nil, repeats: true)
    var timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("updateSlider"), userInfo: nil, repeats: true)

    let pathString = NSBundle.mainBundle().pathForResource("agnes", ofType: "mp3")

    if let pathString = pathString {

        let pathURL = NSURL(fileURLWithPath: pathString)

        do {

            try audioPlayer = AVAudioPlayer(contentsOfURL: pathURL)

        } catch {

            print("error")
        }


    }

    slider.maximumValue = Float(audioPlayer.duration)
}

func updateSlider() {
    slider.value = Float(audioPlayer.currentTime)
    }
}
like image 143
Hunter Avatar answered Mar 03 '23 14:03

Hunter


For the answer of Hunter, It's all right but I would add some lines to the updateTime function. Because like this it doesn't show a time like 1:61 in the label.

    func updateTime() {
    var currentTime = Int(audioPlayer.currentTime)
    var duration = Int(audioPlayer.duration)
    var total = currentTime - duration
    var totalString = String(total)

    var minutes = currentTime/60
    var seconds = currentTime - minutes / 60
    if minutes > 0 {
       seconds = seconds - 60 * minutes
    }

    playedTime.text = NSString(format: "%02d:%02d", minutes,seconds) as String
}
like image 33
Thobbit Avatar answered Mar 03 '23 14:03

Thobbit