«Неверное обновление: недопустимое количество элементов в разделе 0 в моем представлении коллекции - PullRequest
0 голосов
/ 07 декабря 2018

Когда я нажимаю editButton в моем приложении и пытаюсь удалить ячейку в моем collectionView, я получаю следующее сообщение об ошибке:

'Недопустимое обновление: недопустимое количество элементов в разделе 0.Количество элементов, содержащихся в существующем разделе после обновления (3), должно быть равно количеству элементов, содержащихся в этом разделе до обновления (3), плюс или минус количество элементов, вставленных или удаленных из этого раздела (0 вставлено, 1 удалено) и плюс или минус количество элементов, перемещенных в этот раздел или из него (0 перемещено, 0 перемещено). '

После прочтения других аналогичных сообщений Я все еще не был уверен, как применить решение к этой проблеме.Я вижу, что файлы удаляются из FileManager, потому что у меня открыт каталог в Finder, но я не понимаю, как настроить collectionView для синхронизации с количеством файлов в FileManager.

import UIKit
import AVFoundation

class ViewController: UIViewController, AVAudioRecorderDelegate, UICollectionViewDelegate, UICollectionViewDataSource {

    var audioRecorder: AVAudioRecorder!
    var audioPlayer: AVAudioPlayer!
    var numberOfRecordings = 0

    @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)")
        }

    }

    // Let's 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
    }

    // Let's create a genearl 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)
    }

    //MARK: - Record Button Methods
    @IBAction func record(_ sender: Any) {

        if audioRecorder == nil {
            numberOfRecordings += 1
            let fileURL = getDirectory().appendingPathComponent("\(numberOfRecordings).m4a")
            let settings = [
                AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
                AVSampleRateKey: 12000,
                AVNumberOfChannelsKey: 1,
                AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
            ]

            do {
                audioRecorder = try AVAudioRecorder(url: fileURL, settings: settings)
                audioRecorder.delegate = self
                audioRecorder.record()
                recordButton.setTitle("Stop Recording", for: .normal)
            } catch {
                displayAlert(title: "Oops!", message: "Recording Failed")
            }
        } 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
        cell.recordingLabel.text = String(indexPath.row + 1)
        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("\(indexPath.row + 1).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 = isEditing
            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 = !isEditing
                    }
                }
            }
        } else {
            editButton.setTitle("Edit", for: .normal)
            if let indexPaths = myCollectionView?.indexPathsForVisibleItems {
                for indexPath in indexPaths {
                    if let cell = myCollectionView?.cellForItem(at: indexPath) as? RecordingCollectionViewCell {
                        cell.isEditing = isEditing
                    }
                }
            }
        }


    }


}


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
            let fileURL = getDirectory().appendingPathComponent("\(indexPath.row + 1).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. Delete it in the collectionView
            myCollectionView.deleteItems(at: [indexPath])
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

В ошибке четко указано, что для добавления новых строк или удаления существующих строк необходимо внести те же изменения в соответствующий массив, то есть numberOfRecordings .

Например, если вы удаляете 1 строку , вам необходимо внести те же изменения в массив (например, раньше в нем было 3 строки (и в массиве было также 3 элемента), и теперь вы хотите удалить 1 строку, поэтому вам нужно удалить то же количество элементов (т.е. 1) из соответствующего массива (numberOfRecordings)).

То же самое относится и к сложению.

Выполните добавление или удаление из массива перед внесением каких-либо изменений в табличное представление с помощью tableView.deleteRows() или tableView.insertRows()

0 голосов
/ 07 декабря 2018

Вы никогда не обновляете свою модель данных.Помимо удаления файла и сообщения представлению коллекции о том, что элемент был удален, вам также необходимо обновить модель, используемую представлением коллекции.Это означает, что вам нужно обновить numberOfRecordings (перед вызовом myCollectionView.deleteItems(at: [indexPath]).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...