условия:
Episode
- это объект, который содержит source
как строкуСитуация:
Вот моя специальная ячейка: EpisodeCell.swift
import UIKit
protocol EpisodeCellDelegate {
func didTapPlayButton(url: String)
}
class EpisodeCell: UITableViewCell {
var delegate: EpisodeCellDelegate?
var episode: Episode!
let cellView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.init(hex: "#EBE4D3")
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let episodeTitle: UILabel = {
let label = UILabel()
label.textColor = .darkGray
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let playButton: UIButton = {
let btn = UIButton.init(type: .custom)
btn.setTitle("PLAY", for: .normal)
btn.setTitleColor(.gray, for: .normal)
btn.isUserInteractionEnabled = true
btn.addTarget(self, action: #selector(playPressed), for: .touchUpInside)
return btn
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setup()
}
private func setup(){
self.accessoryType = .none
self.addSubview(cellView)
cellView.addSubview(episodeTitle)
cellView.addSubview(playButton)
cellView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
cellView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
cellView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
cellView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
episodeTitle.topAnchor.constraint(equalTo: cellView.topAnchor, constant: 10).isActive = true
episodeTitle.leadingAnchor.constraint(equalTo: cellView.leadingAnchor, constant: 10).isActive = true
episodeTitle.trailingAnchor.constraint(equalTo: cellView.trailingAnchor).isActive = true
episodeTitle.centerYAnchor.constraint(equalTo: cellView.centerYAnchor).isActive = true
playButton.translatesAutoresizingMaskIntoConstraints = false
playButton.trailingAnchor.constraint(equalTo: cellView.trailingAnchor, constant: -10).isActive = true
playButton.centerYAnchor.constraint(equalTo: cellView.centerYAnchor).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("initCoder has not been implemented")
}
@objc func playPressed() {
self.delegate?.didTapPlayButton(url: episode.source)
}
}
И вот, как я реализовал на своем контроллере View с табличным представлением: EpisodesViewController.swift
extension EpisodesViewController: EpisodeCellDelegate {
func didTapPlayButton(url: String) {
print("WOAH: \(url)")
}
}
extension EpisodesViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "episodeCell") as! EpisodeCell
cell.episode = series.episodes![indexPath.row]
cell.episodeTitle.text = ep.episodeName
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (series.episodes?.count)!
}
}
Проблема:
Мне трудно работать с кнопкой, которая будет использоваться в пользовательской ячейке представления таблицы. Мой табличный вид соответствует протоколу, но он не работает.
Вы должны делать ленивую инициализацию для контроля внутри tableviewcell. Ниже код делает магию для меня. Просто измените приведенную ниже часть кода
lazy var cellView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
lazy var episodeTitle: UILabel = {
let label = UILabel()
label.textColor = .darkGray
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
lazy var playButton: UIButton = {
let btn = UIButton.init(type: .custom)
btn.setTitle("PLAY", for: .normal)
btn.setTitleColor(.gray, for: .normal)
btn.isUserInteractionEnabled = true
btn.addTarget(self, action: #selector(playPressed), for: .touchUpInside)
return btn
}()
lazy var
может работать?
У вас не должно быть действий, которые ячейка выполняет внутри ячейки. Ячейки можно повторно использовать, и ячейка, которая была в строке 1, может оказаться в строке 4 в любое время. Вместо вашей процедуры playPressed() используйте традиционный вызов didSelectRowAtIndexPath, который использует IndexPath, а не сама ячейка, чтобы определить действие, которое нужно предпринять.