我有一个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])
}
}
}
答案 0 :(得分:0)
您将recordingTitle
保存在一个变量中,因此每次对其进行重写时,都需要将它们存储为数组。
您可以通过以下方式初始化变量:
var recordingTitles: [String] = []
您使用以下方法添加新标题:
recordingTitles.append(userResponse)
然后您阅读:
let recordingTitle = recordingTitles[indexPath.item]