2015-08-14 67 views
-1
// 
// playSoundsViewController.swift 
// recordVoice 
// 
// Created by david on 11/08/15. 
// Copyright (c) 2015 Tomcorp. All rights reserved. 
// 

import UIKit 
import AVFoundation 


class playSoundsViewController: UIViewController { 

    var audioPlayer:AVAudioPlayer! 
    var receivedAudio:RecordedAudio! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     audioPlayer = AVAudioPlayer(contentsOfURL: receivedAudio.filePathUrl, error: nil) 
     audioPlayer.enableRate = true 
    } 

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


    @IBAction func slowVoice(sender: UIButton) { 
     audioPlayer.stop() 
     audioPlayer.rate = 0.5 
     audioPlayer.currentTime = 0.0 
     audioPlayer.play() 
    } 

    @IBAction func fastVoice(sender: UIButton) { 
      audioPlayer.stop() 
      audioPlayer.rate = 2.0 
      audioPlayer.currentTime = 0.0 
      audioPlayer.play() 
    } 


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

    } 

    /* 
    // MARK: - Navigation 

    // In a storyboard-based application, you will often want to do a little preparation before navigation 
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
     // Get the new view controller using segue.destinationViewController. 
     // Pass the selected object to the new view controller. 
    } 
    */ 


// 
// recordSoundsViewController.swift 
// recordVoice 
// 
// Created by david on 11/08/15. 
// Copyright (c) 2015 Tomcorp. All rights reserved. 
// 

import UIKit 
import AVFoundation 


class recordSoundsViewController: UIViewController, AVAudioRecorderDelegate { 

    @IBOutlet weak var recordButton: UIButton! 
    @IBOutlet weak var recordingLabel: UILabel! 
    @IBOutlet weak var stopButton: UIButton! 

    var audioRecorder:AVAudioRecorder! 
    var recordedAudio:RecordedAudio! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
    } 

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

    override func viewWillAppear(animated: Bool) { 

     stopButton.hidden = true 
     recordButton.enabled = true 

    } 

    @IBAction func recordButton(sender: UIButton) { 

     recordButton.enabled = false 
     stopButton.hidden = false 
     recordingLabel.hidden = false 
     //record voice 



     //Inside func recordAudio(sender: UIButton) 
     let dirPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String 


     let recordingName = "my_audio.wav" 
     let pathArray = [dirPath, recordingName] 
     let filePath = NSURL.fileURLWithPathComponents(pathArray) 
     println(filePath) 

     var session = AVAudioSession.sharedInstance() 
     session.setCategory(AVAudioSessionCategoryPlayAndRecord, error: nil) 

     audioRecorder = AVAudioRecorder(URL: filePath, settings: nil, error: nil) 
     audioRecorder.delegate = self 
     audioRecorder.meteringEnabled = true 
     audioRecorder.record() 

    } 

    func audioRecorderDidFinishRecording(recorder: AVAudioRecorder!, successfully flag: Bool) { 
     if(flag){ 
     recordedAudio = RecordedAudio() 
     recordedAudio.filePathUrl = recorder.url 
     recordedAudio.title = recorder.url.lastPathComponent 
     self.performSegueWithIdentifier("stopRecording", sender: recordedAudio) 
     }else { 
      println("Recording was not successfully") 
      recordButton.enabled = true 
      stopButton.hidden = true 
     } 
    } 

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
     if (segue.identifier == "StopRecording"){ 
      let playSoundsVC:playSoundsViewController = segue.destinationViewController as! playSoundsViewController 
      let data = sender as! RecordedAudio 
      playSoundsVC.receivedAudio = data 

     } 
    } 

    @IBAction func stopButton(sender: UIButton) { 
     recordButton.enabled = true 
     recordingLabel.hidden = true 
     //Inside func stopAudio(sender: UIButton) 
     audioRecorder.stop() 
     var audioSession = AVAudioSession.sharedInstance() 
     audioSession.setActive(false, error: nil) 
    } 

} 

// 
// RecordedAudio.swift 
// recordVoice 
// 
// Created by david on 13/08/15. 
// Copyright (c) 2015 Tomcorp. All rights reserved. 
// 

import Foundation 

class RecordedAudio: NSObject{ 
    var filePathUrl: NSURL! 
    var title: String! 
} 

// 
// AppDelegate.swift 
// recordVoice 
// 
// Created by david on 11/08/15. 
// Copyright (c) 2015 Tomcorp. All rights reserved. 
// 

import UIKit 

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate { 

    var window: UIWindow? 


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
     // Override point for customization after application launch. 
     return true 
    } 

    func applicationWillResignActive(application: UIApplication) { 
     // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
     // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 
    } 

    func applicationDidEnterBackground(application: UIApplication) { 
     // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
     // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 
    } 

    func applicationWillEnterForeground(application: UIApplication) { 
     // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 
    } 

    func applicationDidBecomeActive(application: UIApplication) { 
     // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 
    } 

    func applicationWillTerminate(application: UIApplication) { 
     // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
    } 


} 

這就是它說,在控制檯上後, -5FFA-4964-9AEE-F395D962264F /數據/容器/數據/應用/ A5B7545C-2800-495C-B016-07C3DF010D97 /文檔/ my_audio.wav) 致命錯誤:意外地發現零而展開的可選值崩潰與展開的零值試圖初始化AVAudioPlayer

+0

這些公司的部分其錯誤 – TOMCORP

+0

這些公司的部分其錯誤:audioPlayer = AVAudioPlayer(contentsOfURL:receivedAudio.filePathUrl,錯誤:無) – TOMCORP

回答

0

TOMCORP ,你的代碼充滿了新手的錯誤。有些人會直接對這次事故負責,有些人會遲早會產生問題,有些人只是不能跟上良好的編程習慣。

一切都在評論中解釋。

如果沒有其他人確定要理解「MAJOR ERROR 2」,因爲這與ViewController生命週期有關。在segue標識符上輸入大寫錯誤也是一個嚴重錯誤。

順便說一句,似乎沒有規定從播放VC返回。你需要某種按鈕來執行dismissViewControllerAnimated()

以下代碼在我的Xcode 6.4/iPhone模擬器8.4上正常工作。我遺漏了樣板AppDelegate的代碼。另外請務必放回我在下面省略的'import'聲明。

import UIKit 
import AVFoundation 

// FIX of Error 11 
let stopRecordingSegue = "stopRecording" 

// Error 1: (Style) Class names should always be capitalized 
class PlaySoundsViewController: UIViewController { 
    var audioPlayer: AVAudioPlayer? 

    // MAJOR ERROR 2: viewDidLoad() runs **BEFORE** prepareForSegue(). So it was looking for the 
    // 'recordedAudio' instance variable but prepareForSegue had NOT YET had a chance to 
    // initialize it. 

    // viewDidLoad is the WRONG place for DYNAMIC, RUNTIME initialization. 

    // Instead we make a custom method, called by prepareForSegue(), so we're in full control 
    // of the flow of data from VC to VC. 
    func prepareAudio(receivedAudio: RecordedAudio) { 
     var err: NSError? 
     // Error 3: check carefully for all error conditions 
     if let ap = AVAudioPlayer(contentsOfURL: receivedAudio.filePathUrl, error: &err) { 
      audioPlayer = ap 
      ap.enableRate = true 
     } 
     else { 
      assertionFailure("Exiting program, couldn't create recorder: \(err?.localizedDescription)") 
     } 
    } 

    // Error 4: (Style) Don't have overridden methods that do nothign but call super(). 
    // The clutter just creates confusion. didRecieveMemoryWarning function removed. 

    @IBAction func slowVoice(sender: UIButton) { 
     // Error 5: Handle case where player did not get initialized 
     if let ap = audioPlayer { 
      ap.stop() 
      ap.rate = 0.5 
      ap.currentTime = 0.0 
      ap.play() 
     } 
     else { 
      println("No audioplayer available in slowVoice!") 
     } 
    } 

    @IBAction func fastVoice(sender: UIButton) { 
     // Error 5: Handle case where player did not get initialized 
     if let ap = audioPlayer { 
      ap.stop() 
      ap.rate = 2.0 
      ap.currentTime = 0.0 
      ap.play() 
     } 
     else { 
      println("No audioplayer available in fastVoice!") 
     } 
    } 

    @IBAction func stopButtonSounds(sender: UIButton) { 
     // Error 5: Handle case where player did not get initialized 
     if let ap = audioPlayer { 
      ap.stop() 
     } 
     else { 
      println("No audioplayer available in stop!") 
     } 
    } 

    // Error 6: (Style) Leave out dead code that's commented out. Creates more confusing clutter. 
} 

class RecordSoundsViewController: UIViewController, AVAudioRecorderDelegate { 
    @IBOutlet weak var recordButton: UIButton! 
    @IBOutlet weak var recordingLabel: UILabel! 
    @IBOutlet weak var stopButton: UIButton! 

    var audioRecorder: AVAudioRecorder! 
    var recordedAudio: RecordedAudio! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Error 7: Initialization: All one-time initialization must go in viewDidLoad(), not when the user 
     // pressed a button. Sometimes redundant initialization is not actually harmful, but it's a terrible 
     // programming habit nonetheless. 
     let dirPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String 

     let recordingName = "my_audio.wav" 
     let pathArray = [dirPath, recordingName] 
     let filePath = NSURL.fileURLWithPathComponents(pathArray) 
     println(filePath) 

     // Error 8: Don't create unnecessary variables just to do one-time initialization. Confusing clutter. 
     AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord, error: nil) 

     // Error 9: Don't use 'nil' for error object; receive the error and check it 
     var err: NSError? 
     audioRecorder = AVAudioRecorder(URL: filePath, settings: nil, error: &err) 
     if let e = err { 
      assertionFailure("Exiting program, couldn't create recorder: \(e.localizedDescription)") 
     } 
     else { 
      println("successfully created audio recorder") 
      audioRecorder.delegate = self 
      audioRecorder.meteringEnabled = true 
     } 
    } 

    override func viewWillAppear(animated: Bool) { 
     // Error 10: overriding conventions: Failure to call super of a built-in method like this one 
     super.viewWillAppear(animated) 
     stopButton.hidden = true 
     recordButton.enabled = true 
    } 

    @IBAction func recordButton(sender: UIButton) { 
     recordButton.enabled = false 
     stopButton.hidden = false 
     recordingLabel.hidden = false 

     audioRecorder.record() 
    } 

    func audioRecorderDidFinishRecording(recorder: AVAudioRecorder!, successfully flag: Bool) { 
     if flag { 
      recordedAudio = RecordedAudio() 
      recordedAudio.filePathUrl = recorder.url 
      recordedAudio.title = recorder.url.lastPathComponent 
      // Error 11: sender should be the actual initiating VC 
      self.performSegueWithIdentifier(stopRecordingSegue, sender: self) 
     } 
     else { 
      println("Recording was not successful") // Error 12: Grammar 
      recordButton.enabled = true 
      stopButton.hidden = true 
     } 
    } 

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
     // Error 13: Not using a defined constant string, you've messed up capitalization 
     if segue.identifier == stopRecordingSegue { 
      let playSoundsVC = segue.destinationViewController as! PlaySoundsViewController 
      // REST OF FIX OF MAJOR ERROR 2: send in data to a method so runtime initialization code can run 
      playSoundsVC.prepareAudio(recordedAudio) 
     } 
    } 

    @IBAction func stopButton(sender: UIButton) { 
     recordButton.enabled = true 
     recordingLabel.hidden = true 
     audioRecorder.stop() 
     AVAudioSession.sharedInstance().setActive(false, error: nil) 
    } 
} 

class RecordedAudio: NSObject{ 
    var filePathUrl: NSURL! 
    var title: String! 
} 
+0

你好日Thnx的評論,但它不工作,我不知道爲什麼它說它是一個致命的錯誤:意外地發現零,同時解開一個可選值 – TOMCORP

+0

你用我的viewDidLoad()替換,仍然有這個錯誤?在哪一行? – BaseZen

+0

我在代碼的不同部分出現了錯誤,每個audioRecorder都會讓我對audioRecorder進行更改!然後工作,但不重現記錄的聲音 – TOMCORP