问题
So I have dynamic tableview and each row have play image. If I select the row image will change to pause icon. But what if I select another row, I need the image on previously selected row to have play icon again. How to handle such functionality?
All I have is:
class ViewController: UIViewController {
var stations = [
(stationIcon: "rr_icon", stationName: "Radio1", urlString: "http://.._320", isPlaying: false),
(stationIcon: "mm_icon", stationName: "Record2", urlString: "http://../_320", isPlaying: false),
........]
func playSelectedStation(indexPath: NSIndexPath) {
let url = NSURL(string: stations[indexPath.row].urlString)!
stations[indexPath.row].isPlaying = true
avPlayer = AVPlayer(URL: url)
avPlayer.play()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! RadioTableViewCell
cell.playPause.image = stations[indexPath.row].isPlaying ? UIImage(named: "cellPause") : UIImage(named: "cellPlay")
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
switch indexPath.row {
playSelectedStation(indexPath)
tableView.reloadData()
Radio Stations are changing without problem, having issue only with play/pause icon state
回答1:
You can achieve it by going through visible cells and disable play button in all of them except the one the user has just tapped on:
class PlayItem {
// your code
var isPlaying = false
}
class RadioTableViewCell: UITableViewCell {
// your code ....
func setup(item item: PlayItem) {
image = item.isPlaying ? UIImage(named: "cellPause") : UIImage(named: "cellPlay")
}
}
In your delegate:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! RadioTableViewCell
let item = items[indexPath.row] // you may think of storing this array in some kind of view model
cell.setup(item: item)
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let selectedCell = tableView.cellForRowAtIndexPath(indexPath) as! RadioTableViewCell
let selectedItem = items[indexPath.row]
selectedItem.isPlaying = !selectedItem.isPlaying
for cell in tableView.visibleCells {
guard let visibleCell = cell as? RadioTableViewCell else { return }
let path = tableView.indexPathForCell(visibleCell)
let item = items[path.row]
item.isPlaying = visibleCell == selectedCell
visibleCell.setup(item: item)
}
}
UPDATE: I have updated my answer to store the playback state in item.
回答2:
Use the MVC pattern instead of storing data in the view object or the global(view controller) scope. Then your life will be much easier.
I think each row should be backed by a model object. Say:
class PlayItem {
....
var isPlaying = false
}
then your cellForRowAtIndexPath
method:
let playItem = self.playItemArray[indexPath.row]
cell.imageView.image = playItem.isPlaying ? UIImage("cellPause") : UIImage("cellPlay")
then in your didSelectRowAtIndexPath
method, change the selected item isPlaying = true
and all the other items isPlaying = false
, and call tableView.reloadData()
. The table view will refresh all the cells to reflect their correct state.
来源:https://stackoverflow.com/questions/38390281/how-to-change-image-to-previous-state-if-other-row-is-selected-in-tableview-dids