无法将录制的文件列出到 TableView

Posted

技术标签:

【中文标题】无法将录制的文件列出到 TableView【英文标题】:Cannot list recorded files to a TableView 【发布时间】:2016-07-24 20:42:04 【问题描述】:

我急需帮助,因为我的头被撞到墙上真的很痛。

我有一个视图控制器,我在其中使用麦克风录制音频并将其保存到应用程序文档目录中。这运行良好,如果我导航到模拟器中的该文件夹,我可以看到这些文件。

我的问题是我有一个带有自己的 TableViewController 的 TableView,我想在其中列出包含我的录音的文档目录的内容。我创建了 TableView,它正在读取和填充基于基本数组的表。我的问题是我无法将其转换为读取文档目录内容。

我对此表有未来的目标,还允许我通过滑动特定单元格在此 TableView 中播放、删除或重命名文件。

我已经在这个问题上工作了大约 5 天,我确信我忽略了一些对你们来说非常简单的事情。

我正在使用 Xcode 7.3.1 和 Swift 2。

提前致谢,我迫不及待地想做出贡献。

ViewControllerRecorder.swift (这是我录制音频并将其保存到正在工作的文档目录的位置。)

import UIKit
import AVFoundation
import PermissionScope

class ViewControllerRecorder: UIViewController, AVAudioRecorderDelegate, AVAudioPlayerDelegate 

    @IBOutlet weak var stopButton: UIButton!
    @IBOutlet weak var recordButton: UIButton!
    @IBOutlet weak var playButton: UIButton!

    @IBOutlet weak var audioDuration: UISlider!


    var audioRecorder:AVAudioRecorder?
    var audioPlayer:AVAudioPlayer?

    let pscope = PermissionScope()


    override func viewDidLoad() 
        super.viewDidLoad()

        audioDuration.value = 0.0

        // Set up permissions
        pscope.addPermission(MicrophonePermission(),
                             message: "Inorder to use this app, you need to grant the microphone permission")

        // Show dialog with callbacks
        pscope.show( finished, results in
            print("got results \(results)")
            , cancelled:  (results) -> Void in
                print("thing was cancelled")
        )

        // Disable Stop/Play button when application launches
        stopButton.enabled = false
        playButton.enabled = false




        // Get the document directory. If fails, just skip the rest of the code
        guard let directoryURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).first else 

            let alertMessage = UIAlertController(title: "Error", message: "Failed to get the document directory for recording the audio. Please try again later.", preferredStyle: .Alert)
            alertMessage.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
            presentViewController(alertMessage, animated: true, completion: nil)

            return
        

        // Set the default audio file
        let audioFileURL = directoryURL.URLByAppendingPathComponent("PWAC_" + NSUUID().UUIDString + ".m4a")

        // Setup audio session
        let audiosession = AVAudioSession.sharedInstance()

        do 
            try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions: AVAudioSessionCategoryOptions.DefaultToSpeaker)




            // Define the recorder setting
            let recorderSetting: [String: AnyObject] = [
                AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
                AVSampleRateKey: 32000.0,
                AVNumberOfChannelsKey: 2,
                AVEncoderAudioQualityKey: AVAudioQuality.Medium.rawValue
            ]

            // Initiate and prepare the recorder
            audioRecorder = try AVAudioRecorder(URL: audioFileURL, settings: recorderSetting)
            audioRecorder?.delegate = self
            audioRecorder?.meteringEnabled = true
            audioRecorder?.prepareToRecord()

         catch 
            print(error)
        

    


    func updateaudioDuration()

        audioDuration.value = Float(audioPlayer!.currentTime)
    

    @IBAction func sliderAction(sender: AnyObject) 


        audioPlayer!.currentTime = NSTimeInterval(audioDuration.value)

    

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

    @IBAction func play(sender: AnyObject) 
        if let recorder = audioRecorder 
            if !recorder.recording 
                do 
                    audioPlayer = try AVAudioPlayer(contentsOfURL: recorder.url)

                    audioDuration.maximumValue = Float(audioPlayer!.duration)
                    _ = NSTimer.scheduledTimerWithTimeInterval(0.05, target: self, selector: #selector(ViewControllerRecorder.updateaudioDuration), userInfo: nil, repeats: true)

                    audioPlayer?.delegate = self
                    audioPlayer?.play()
                    playButton.setImage(UIImage(named: "playing"), forState: UIControlState.Selected)
                    playButton.selected = true
                 catch 
                    print(error)
                
            
        
    

    @IBAction func stop(sender: AnyObject) 
        recordButton.setImage(UIImage(named: "record"), forState: UIControlState.Normal)
        recordButton.selected = false
        playButton.setImage(UIImage(named: "play"), forState: UIControlState.Normal)
        playButton.selected = false

        stopButton.enabled = false
        playButton.enabled = true

        audioRecorder?.stop()

        let audioSession = AVAudioSession.sharedInstance()

        do 
            try audioSession.setActive(false)
         catch 
            print(error)
        
    

    @IBAction func record(sender: AnyObject) 
        // Stop the audio player before recording
        if let player = audioPlayer 
            if player.playing 
                player.stop()
                playButton.setImage(UIImage(named: "play"), forState: UIControlState.Normal)
                playButton.selected = false
            
        

        if let recorder = audioRecorder 
            if !recorder.recording 
                let audioSession = AVAudioSession.sharedInstance()

                do 
                    try audioSession.setActive(true)

                    // Start recording
                    recorder.record()
                    recordButton.setImage(UIImage(named: "recording"), forState: UIControlState.Selected)
                    recordButton.selected = true


                 catch 
                    print(error)
                

             else 
                // Pause recording
                recorder.pause()
                recordButton.setImage(UIImage(named: "pause"), forState: UIControlState.Normal)
                recordButton.selected = false
            
        

        stopButton.enabled = true
        playButton.enabled = false

    


    // MARK: - AVAudioRecorderDelegate Methods
    func audioRecorderDidFinishRecording(recorder: AVAudioRecorder, successfully flag: Bool) 
        if flag 

            // iOS8 and later
            let alert = UIAlertController(title: "Recorder",
                                          message: "Finished Recording",
                                          preferredStyle: .Alert)
            alert.addAction(UIAlertAction(title: "Keep", style: .Default, handler: action in
                print("keep was tapped")
            ))
            alert.addAction(UIAlertAction(title: "Delete", style: .Default, handler: action in
                print("delete was tapped")
                self.audioRecorder!.deleteRecording()
            ))

            self.presentViewController(alert, animated:true, completion:nil)

//            let alertMessage = UIAlertController(title: "Finish Recording", message: "Successfully recorded the audio!", preferredStyle: .Alert)
//            alertMessage.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
//            presentViewController(alertMessage, animated: true, completion: nil)
            print("Audio has finished recording")
            print(recorder.url)
        
    

    // MARK: - AVAudioPlayerDelegate Methods
    func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) 
        playButton.setImage(UIImage(named: "play"), forState: UIControlState.Normal)
        playButton.selected = false

        let alertMessage = UIAlertController(title: "Finish Playing", message: "Finish playing the recording!", preferredStyle: .Alert)
        alertMessage.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
        presentViewController(alertMessage, animated: true, completion: nil)
        print("Audio has finished playing")
        print(player.url)
    



ViewControllerFileManager.swift (这是我想将文档目录的内容显示到 TableView 的视图控制器。)

2016 年 7 月 27 日更新

import UIKit

class ViewControllerFileManager: UIViewController, UITableViewDataSource, UITableViewDelegate 

var arrayRecordings = [String]()

override func viewDidLoad() 
    super.viewDidLoad()

    let fileManager = NSFileManager.defaultManager()
    let dirPath = NSBundle.mainBundle().resourcePath!


    let items = try! fileManager.contentsOfDirectoryAtPath(dirPath)

    for item in items 
        if item.hasSuffix("m4a") 

            arrayRecordings.append(item)

        
        print("Found \(item)")
    



    // 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.



func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    // Return the number of rows in the section.
    return arrayRecordings.count


func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    let cellIdentifier = "Cell"
    let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)



    // Configure the cell...


    cell.textLabel?.text = arrayRecordings[indexPath.row]
    return cell


override func prefersStatusBarHidden() -> Bool 
    return true



【问题讨论】:

嗨!您是否已经检查过此线程:***.com/questions/8376511/…? 您好 fiks,确实这是我尝试过的线程之一。即使认为这似乎是我的答案,我似乎也无法让它工作。我确定我将代码放在错误的位置。根据我的“ViewControllerFileManager”,您能否指导我正确实施? 我会加载 viewDidLoad 中的文件。你试过这个吗?如果是,但它不起作用,我可以花一些时间根据你的代码实现一些东西。 我也试过了,我一定是搞砸了。此外,当我输入您向我发送链接的该页面上显示的代码时,我收到了许多错误。 如何在 ViewController 类中填充recordingFileNames 变量? 【参考方案1】:

如果你在 viewDidLoad 中填充数组,你需要调用 tableView 的 reloadData 来刷新它。

override func viewDidLoad()
 
   super.viewDidLoad()

   // populate recordingFileNames here

   // refresh your table
   reloadTableViewContent()
  

 func reloadTableViewContent()
 
    dispatch_async(dispatch_get_main_queue(),  () -> Void in
      self.tableView.reloadData()
      self.tableView.scrollRectToVisible(CGRectMake(0, 0, 1, 1), animated: false)
    )
 

【讨论】:

【参考方案2】:

这是我使用我的应用程序文档文件夹的内容填充 TableView 的代码

import UIKit

class ViewControllerFileManager: UIViewController, UITableViewDataSource, UITableViewDelegate 



    var arrayRecordings = [String]()



    override func viewDidLoad() 
        super.viewDidLoad()

        // MARK: Read Document Directory and populate Array

        // Get the document directory url:
        let documentsUrl =  NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!

        do 
            // Get the directory contents urls (including subfolders urls):
            let directoryContents = try NSFileManager.defaultManager().contentsOfDirectoryAtURL( documentsUrl, includingPropertiesForKeys: nil, options: [])
            print(directoryContents)

            // Filter directory contents:
            let audioFiles = directoryContents.filter $0.pathExtension == "m4a" 
            print("m4a urls:",audioFiles)

            // Get the File Names:
            let audioFileNames = audioFiles.flatMap($0.URLByDeletingPathExtension?.lastPathComponent)
            print("m4a list:", audioFileNames)

            for audioFileName in audioFileNames 
                arrayRecordings.append(audioFileName)
                print("Found \(audioFileName)")
            


         catch let error as NSError 
            print(error.localizedDescription)
        

    


    // MARK: TableView Functions
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        // Return the number of rows in the section.
        return arrayRecordings.count
    



    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

        let cellIdentifier = "Cell"
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)


        // Configure the cell...
        cell.textLabel?.text = arrayRecordings[indexPath.row]
        return cell
    


    // MARK: Standard Functions
    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    



    override func prefersStatusBarHidden() -> Bool 
        return true
    



【讨论】:

以上是关于无法将录制的文件列出到 TableView的主要内容,如果未能解决你的问题,请参考以下文章

使用 PhoneGap 将音频录制到 iOS 上的文档文件夹

录制音频,添加效果,然后将结果保存到音频文件

使用 JMF 将多路复用的音频/视频录制到文件中

以指定的时间间隔录制视频,然后将它们保存到文件 OpenCv Python

录制音频并保存到文档目录后无法使用 AVAudioPlayer 播放音频文件

无法使用 AVFoundation 将录制的视频上传到服务器 - Swift 3