#swift
#swift
Вопрос:
Я пытаюсь отфильтровать массив песен, чтобы в нем были только песни, в которых имя исполнителя песни совпадает с именем исполнителя (которое всегда является выбранным исполнителем). Когда я запускаю свое приложение, оно выдает фатальную ошибку: индекс вне диапазона, хотя в моей консоли отладки artistSongs
есть 4 элемента. Я не понимаю, как я получаю этот сбой.
override func viewDidLoad() {
super.viewDidLoad()
retriveData()
//Register nib
topSongTableView.register(TopSongTableViewCell.nib(), forCellReuseIdentifier: TopSongTableViewCell.topSongCell)
ArtistPicture.image = artistCover
ArtistLabel.text = ArtistName
//Assign TableView to self
topSongTableView.delegate = self
topSongTableView.dataSource = self
}
//Define number of rows in topSongsTableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
// songs of artist
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TopSongTableViewCell", for: indexPath) as! TopSongTableViewCell
let artistSongs = songs.filter{ $0.artistName == ArtistName }
print(artistSongs)
cell.TopSongLabel.text = artistSongs[indexPath.row].cleanName //CASH
cell.SongImage.image = UIImage(named: artistSongs[indexPath.row].cover)
return cell
}
Комментарии:
1. $ 0.artistName == artistName , какой тип artistName? а имя исполнителя — это класс?
2. @luffy_064 Имя исполнителя — это переменная строка, которая заполняется, когда пользователь выбирает исполнителя из другого табличного представления. Смысл этого в том, чтобы иметь только песни с этим именем исполнителя.
3. вы никогда не должны выполнять фильтр внутри cellForRow. Переместите свой метод фильтрации в viewDidLoad или любой другой метод.
Ответ №1:
Ваша проблема в том, что ваш TableView topSongTableView
ожидает отображения 5 строк (вы это жестко запрограммировали), но когда вы удаляете свои ячейки из очереди, вы также фильтруете artistSongs
одновременно (это не должно быть сделано здесь), и это создает в вашем случае массив с менее чем 5 элементами (4 в вашем случае).
Итак, здесь func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
вы пытаетесь удалить из очереди больше ячеек, чем элементов artistSongs
.
Допустим let artistSongs = songs.filter{ $0.artistName == ArtistName }
, создается массив только из 3 элементов, но ваше табличное представление ожидает 5, когда вы отменяете очередь своих ячеек и пытаетесь получить доступ к песне artistSongs[indexPath.row]
, она будет работать для первых 3 строк, а затем произойдет сбой (ваш текущий сбой).
Ваше решение — отфильтровать песни исполнителя где-нибудь в другом месте, скажем, в viewDidLoad
, а затем использовать этот массив для безопасного заполнения вашего табличного представления:
// ADD THIS
var filteredSongs: [Song]()
override func viewDidLoad() {
super.viewDidLoad()
[...]
// ADD THIS
self.filteredSongs = songs.filter{ $0.artistName == ArtistName }
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// CHANGE THIS
return self.filteredSongs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TopSongTableViewCell", for: indexPath) as! TopSongTableViewCell
// REMOVE THIS
//let artistSongs = songs.filter{ $0.artistName == ArtistName }
// REMOVE THIS
//print(artistSongs)
cell.TopSongLabel.text = self.filteredSongs[indexPath.row].cleanName
cell.SongImage.image = UIImage(named: self.filteredSongs[indexPath.row].cover)
return cell
}
Комментарии:
1. Я уверен, что ваше решение правильное, но похоже, что вы объявляете новый массив
var artistSongs: [ArtistSong]()
. Мне все еще нужны данные изsongs
массива, чтобы отображаться в моем табличном представлении.2. Я получаю эту ошибку в
self.artistSong
строке, не удается присвоить значение типа ‘[Песни]’ типу ‘[Строка]’3. Я обновил пример и переименовал artistSongs в filteredSongs, чтобы быть более понятным. Насколько я понимаю, у вас есть массив песен где-то в вашем контроллере представления, и вы хотите отфильтровать этот массив благодаря artistName , а затем отобразить эти отфильтрованные песни в вашем табличном представлении — вот почему я объявил новый массив, который может безопасно использоваться в вашем табличном представлении.
4.
var filteredSongs: [Song]()
решена моя проблема в предыдущем комментарии. Спасибо! Особенно для указания на то, что я должен фильтровать свой массив в viewDidLoad.