Привет! Делаю плеер, заполнил таблицу при помощи json массива, кнопки работают и музыка играет. Но возникла проблема со сменой картинок у кнопки, тобишь чтобы при нажатии на кнопку, сменилась картинка, затем если нажал плей на другой песне, то картинка у первой сбросилась. Я пробовал это сделать через массив со всеми нажатыми кнопками и сбрасывал их каждый раз. Но тут проблема в том, что если я нажал плей на 1 музыке, сменяется картинка и у другой песни и так через каждые 6 строк.
Смена картинки у кнопки при нажатии
Похоже, это из-за того, что таблица использует reusable-ячейки. При обработке события нажатия на кнопку нужно не только менять картинку, но и запоминать состояние кнопки. А в функции делегата tableView(cellForRowAt:) подставлять картинку в зависимости от состояния кнопки.
Например, так (код очень примерный и не проверялся на работоспособность):
enum SongState {
case playing, stopped, undefined //etc
}
struct Song {
var name = ""
var artist = ""
var audioFile = ""
var pictureFile = ""
var state: SongState = .undefined
}
//...
//данные для таблицы
let playList = [Song]()
//...
//допустим класс ячейки называется Cell
@objc private func myCoolButton_Pressed(sender: UIButton) {
guard let cell = sender.findClass(type: Cell.self) else {return}
guard let indexPath = self.tableView.indexPath(for: cell) else { return }
if playList[indexPath.row].state == .undefined {
playList[indexPath.row].state = .playing
sender.setImage(UIImage(named: "mypic_playing"), for: .normal)
//сбросить состояние у других кнопок, пробежавшись по массиву
}
}
//...
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! Cell
//вот тут назначаем картинки в зависимости от состояния
switch playList[indexPath.row].state {
case .undefined:
cell.myCoolButton.setImage(UIImage(named: "mypic_undefined"), for: .normal)
case .playing:
cell.myCoolButton.setImage(UIImage(named: "mypic_playing"), for: .normal)
default:
cell.myCoolButton.setImage(UIImage(named: "mypic_some_state"), for: .normal)
break
}
return cell
}
//небольшой extension для поиска нужного view вверх по дереву
extension UIView {
func findClass<T>(type: T.Type) -> T? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.next
if let view = parentResponder as? T {
return view
}
}
return nil
}
}
не совсем понял, почему свич работает по состоянию массива с песнями, у массива же нет свойства state
В моем примере плейлист - это массив из структур Song
let playList = [Song]()
Song выглядит так:
struct Song {
var name = ""
var artist = ""
var audioFile = ""
var pictureFile = ""
var state: SongState = .undefined
}
В поле структуры state мы сохраняем состояние песни и в зависимости от этого состояния назначаем кнопке картинку.
Кстати, после того, как при нажатии на кнопку вы установили состояние и изменили состояние у других кнопок, нужно сделать reloadData у таблицы, чтобы обновить ячейки.
Нету, поэтому я написал extension.
//небольшой extension для поиска нужного view вверх по дереву
extension UIView {
func findClass<T>(type: T.Type) -> T? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.next
if let view = parentResponder as? T {
return view
}
}
return nil
}
}
и последний вопрос надеюсь) Ругается на guard let cell = sender.findClass(type: Cell.self) else {return} ,
Use of unresolved identifier ‘Cell’
Правильно ругается. Я же не знаю, как вы назвали ваш класс прототипа ячейки. Поэтому для примера написал “Cell”. Если у вас класс ячейки называется MyAwesomeCell, то так и пишите sender.findClass(type: MyAwesomeCell.self).
вроде все настроил)
также, отключить форматирование текста можно, начав строку с четырех пробелов
вот тут нужно было пробежаться по массиву playlist и сбросить состояние до .undefined ведь так? Теперь ругается на Cannot assign to property: ‘i’ is a ‘let’ constant
guard let cell = sender.findClass(type: UIT.self) else {return}
guard let indexPath = self.tableView.indexPath(for: cell) else { return }
if playList[indexPath.row].state == .undefined {
playList[indexPath.row].state = .playing
for i in playList {
i.state = .undefined
}
sender.setBackgroundImage(UIImage(named: "btnPlay-2.png"), for: UIControlState.normal)
}
поправил, просто сделал так
for i in 0…playList.count-1 {
if (i != indexPath.row) {
playList[i].state = .undefined
}
}
спасибо большое! все работает!