集合视图单元格标签会覆盖其他单元格的标签

时间:2018-12-12 21:14:29

标签: swift uicollectionview uicollectionviewcell

我有一个UICollectionView,其中使用UIAlert的输入为每个单元格创建标签(recordingTitle)。但是,此刻来自警报的任何新输入都会覆盖UICollectionView中所有先前创建的单元格的标签。我如何让每个单元格都有一个单独的标签?

import UIKit
import AVFoundation

class ViewController: UIViewController, AVAudioRecorderDelegate, UICollectionViewDelegate, UICollectionViewDataSource {

    var audioRecorder: AVAudioRecorder?=nil
    var audioPlayer: AVAudioPlayer!
    var numberOfRecordings = 0
    var recordingTitle: String = ""
    var fileURL: URL!

    @IBOutlet weak var recordButton: UIButton!
    @IBOutlet weak var editButton: UIButton!
    @IBOutlet weak var myCollectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()

        recordButton.layer.cornerRadius = 10
        editButton.layer.cornerRadius = 10


        // Set the numberOfRecordings to be exactly the number of files stored in the File Manager so that they're in sync
        let fileManager = FileManager.default
        let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
        do {
            let fileURLs = try fileManager.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
            numberOfRecordings = fileURLs.count
        } catch {
            print("Error while enumerating files \(documentsURL.path): \(error.localizedDescription)")
        }

    }

    // Get the directory where we're going to store the recordings
    func getDirectory() -> URL {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let documentDirectory = paths[0]
        return documentDirectory
    }

    // Create a general alert to display error messages
    func displayAlert(title: String, message: String) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
        present(alert, animated: true, completion: nil)
    }


    // Create an alert to ask for recording title input
    func askForRecordingTitle() {
        let alertController = UIAlertController(title: "Recording Title", message: nil, preferredStyle: .alert)
        alertController.addTextField(configurationHandler: nil)
        let submitAction = UIAlertAction(title: "Save", style: .default) { [weak self] (alertAction) in
            guard let `self` = self else { return }

            if let userResponse = alertController.textFields?[0].text {
                self.recordingTitle = userResponse
                let fileURL = self.getDirectory().appendingPathComponent("\(self.recordingTitle).m4a")
                self.fileURL = fileURL

                let settings = [
                    AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
                    AVSampleRateKey: 12000,
                    AVNumberOfChannelsKey: 1,
                    AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
                ]

                do {
                    let audioRecorder = try AVAudioRecorder(url: fileURL, settings: settings)
                    audioRecorder.delegate = self
                    audioRecorder.record()
                    self.recordButton.setTitle("Stop Recording", for: .normal)
                    self.audioRecorder = audioRecorder
                } catch {
                    self.displayAlert(title: "Oops!", message: "Recording Failed")
                }


            } else {
                print("Not nil or a value")
            }
        }
        alertController.addAction(submitAction)
        present(alertController, animated: true, completion: nil)
    }

    //MARK: - Record Button Methods
    @IBAction func recordAction(_ sender: Any) {
        if audioRecorder == nil {
            askForRecordingTitle()
            numberOfRecordings += 1
        } else {
            audioRecorder?.stop()
            audioRecorder = nil
            UserDefaults.standard.set(numberOfRecordings, forKey: "numberOfRecordings")
            recordButton.setTitle("Start Recording", for: .normal)
            myCollectionView.reloadData()
        }
    }


    //MARK: - Collection View Setup
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return numberOfRecordings
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! RecordingCollectionViewCell

        if editButton.titleLabel?.text == "Stop Editing" {
            cell.isEditing = true
        }   else {
            cell.isEditing = false
        }
        cell.recordingLabel.text = recordingTitle
        cell.layer.cornerRadius = 10
        cell.delegate = self as RecordingCellDelegate
        return cell
    }

    //MARK: - Audio Player
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let path = getDirectory().appendingPathComponent("\(recordingTitle).m4a")

        do {
            audioPlayer = try AVAudioPlayer(contentsOf: path)
            audioPlayer.volume = 1.0
            audioPlayer.prepareToPlay()
            audioPlayer.play()
        } catch let error {
            print("Error: \(error.localizedDescription)")
        }
    }

    //MARK: - Edit Button Methods
    @IBAction func editButtonTapped(_ sender: Any) {
        if editButton.titleLabel?.text == "Edit" {
            recordButton.isEnabled = false
            editButton.setTitle("Stop Editing", for: .normal)
            if let indexPaths = myCollectionView?.indexPathsForVisibleItems {
                for indexPath in indexPaths {
                    if let cell = myCollectionView?.cellForItem(at: indexPath) as? RecordingCollectionViewCell {
                        cell.isEditing = true
                    }
                }
            }
        } else {
            editButton.setTitle("Edit", for: .normal)
            recordButton.isEnabled = true
            if let indexPaths = myCollectionView?.indexPathsForVisibleItems {
                for indexPath in indexPaths {
                    if let cell = myCollectionView?.cellForItem(at: indexPath) as? RecordingCollectionViewCell {
                        cell.isEditing = false
                    }
                }
            }
        }


    }


}


extension ViewController: RecordingCellDelegate {
    func delete(cell: RecordingCollectionViewCell) {
        if let indexPath = myCollectionView?.indexPath(for: cell) {
            // 1. Delete the recording from the File Manager
            let fileManager = FileManager.default
            fileURL = getDirectory().appendingPathComponent("\(recordingTitle).m4a")
            do {
                try fileManager.removeItem(at: fileURL)

            }   catch let error {
                print("File not found: \(error.localizedDescription)")
                displayAlert(title: "Oops!", message: "File not found: \(error.localizedDescription)")
            }

            // 2. Update the data model
            let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
            do {
                let fileURLs = try fileManager.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
                numberOfRecordings = fileURLs.count
            } catch {
                print("Error while enumerating files \(documentsURL.path): \(error.localizedDescription)")
            }


            // 3. Delete cell in the collectionView
            myCollectionView.deleteItems(at: [indexPath])
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您将recordingTitle保存在一个变量中,因此每次对其进行重写时,都需要将它们存储为数组。

您可以通过以下方式初始化变量:

var recordingTitles: [String] = []

您使用以下方法添加新标题:

recordingTitles.append(userResponse)

然后您阅读:

let recordingTitle = recordingTitles[indexPath.item]