在 TableView 中更改图像按钮
change image button in TableView
我在 tableView 中有一个音频播放器,它可以在按钮的帮助下工作。问题是:单击按钮时如何更改按钮的图标。我设法更改了图标,但它无法正常工作,并且当我按 2 次按钮时速度明显变慢。
GIF 工作原理:
var boolValue = false
class TableViewControllerAudioList: UIView,UITableViewDelegate,UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var avplayer:AVPlayer!
override func setNeedsDisplay() {
super.setNeedsDisplay()
}
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return modalsF.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCellAudioList
cell.name.text = modalsF[indexPath.row].AudioName
cell.duration.text = "00:00"
cell.number.text = "\(indexPath.row + 1)"
cell.playChange.tag = indexPath.row
cell.playChange.addTarget(self, action: #selector(tickClicked), for: .touchUpInside)
cell.tapAction = { (cell) in
// self.player = self.setupAudioPlayerWithFile(file: "https:---.com" + modalsF[indexPath.row].UrlName! as NSString, type: "mp3")
self.avplayer = self.pl(file: "https:---.com" + modalsF[indexPath.row].UrlName! as NSString)
// self.play(tableView.indexPath(for: cell)!.row)
}
return cell
}
func tickClicked(_ sender: UIButton!) {
print(sender.tag)
let cellTop = tableView.cellForRow(at: NSIndexPath(row: sender.tag, section: 0) as IndexPath) as!TableViewCellAudioList
if boolValue == false{
cellTop.playChange.setImage(UIImage(named:"Pause.png"), for: UIControlState.normal)
boolValue = true
} else {
cellTop.playChange.setImage(UIImage(named:"Play.png"), for: UIControlState.normal)
boolValue = false
}
}
func pl(file:NSString) -> AVPlayer? {
let url = URL(string: file as String)
let avPlayer: AVPlayer?
let playerItem = AVPlayerItem(url: url!)
avPlayer = AVPlayer(playerItem:playerItem)
if avPlayer?.rate == 0 {
avPlayer?.play()
avPlayer?.rate = 1.0
} else if avPlayer?.rate == 1{
avPlayer?.pause()
}
return avPlayer
}
TableViewCell:
class TableViewCellAudioList: UITableViewCell {
@IBOutlet weak var number: UILabel!
@IBOutlet weak var name: UILabel!
@IBOutlet weak var duration: UILabel!
@IBOutlet weak var playChange: UIButton!
var tapAction: ((UITableViewCell) -> Void)?
@IBAction func playAudio(_ sender: Any) {
tapAction?(self)
}
}
编辑:
我想速度变慢的问题是您以相同的点击方式开始播放。在创建 AVAudioPlayer
实例之前,您在内存中读取了整个文件。这很慢,很可能是您速度变慢的原因。
您不需要将文件加载到内存中,您可以从文件中播放 -
docs。我不是 100% 确定 AVAudioPlayer 是如何在内部工作的,但它可能会减少你的减速。
为了消除减速,您可以在单独的线程中开始播放,或者尝试使用 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 /*seconds*/, execute: {
从当前运行循环周期推迟播放。这应该允许 UIKit 完成所有重绘操作,您应该可以快速更改。 在 之后调度可能是一种快速而肮脏的解决方案,但您需要实际测量开始播放时的减速程度,并决定是否可以将其保留在主线程中。
编辑:在评论中讨论并意识到您不是从磁盘而是从互联网加载文件。
您可能想看看 AVPlayer 而不是 AVAudioPlayer。您的问题是您从 Internet 加载整个文件,这在主线程中 VERY 很慢。 AVPlayer 允许通过 "streaming" 播放远程文件。有了它,您就不必等待整个文件下载。
另一个选项是预下载文件,但这不在本题的讨论范围内。
更改以下方法,需要一些时间才能播放
func tickClicked(_ sender: UIButton!) {
print(sender.tag)
// add me on linkdin from vibha singh for further help
let cellTop = tableView.cellForRow(at: NSIndexPath(row: sender.tag, section: 0) as IndexPath) as!TableViewCellAudioList
// Check for current status of button selection
let checkSelectedStatus = modalsF[sender.tag].isSelected
let currentag = sender.tag
if(checkSelectedStatus == "0")
{
modalsF[sender.tag].isSelected = "1"
avPlayer?.cancelPendingPrerolls()
let _ = avPlayer?.addPeriodicTimeObserver(forInterval: CMTime(seconds: 0.1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: DispatchQueue.main)
{ [] (time) in
// update slider
let duration = CMTimeGetSeconds((avPlayer?.currentItem!.asset.duration)!)
let someVal : Float = Float(CMTimeGetSeconds(time)) / Float(duration)
modalsF[currentag].BarProgressVal = someVal
print("Some val \(someVal)")
print("Current tag \(currentag)")
self.tableView.reloadData()
}
// If 0 then set 1 so that while table scroll it will not change value
cellTop.playChange.setImage(UIImage(named:"Pause.png"), for: UIControlState.normal)
} else
{
modalsF[sender.tag].isSelected = "0" //If 1 then set 0 so that while table scroll it will not change value
cellTop.playChange.setImage(UIImage(named:"Play.png"), for: UIControlState.normal)
}
// this will play at a time one audio
if(lastSelectedcount != 40000 && lastSelectedcount != sender.tag) {
modalsF[lastSelectedcount].isSelected = "0"
}
self.tableView.reloadData()
}
我在 tableView 中有一个音频播放器,它可以在按钮的帮助下工作。问题是:单击按钮时如何更改按钮的图标。我设法更改了图标,但它无法正常工作,并且当我按 2 次按钮时速度明显变慢。
GIF 工作原理:
var boolValue = false
class TableViewControllerAudioList: UIView,UITableViewDelegate,UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var avplayer:AVPlayer!
override func setNeedsDisplay() {
super.setNeedsDisplay()
}
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return modalsF.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCellAudioList
cell.name.text = modalsF[indexPath.row].AudioName
cell.duration.text = "00:00"
cell.number.text = "\(indexPath.row + 1)"
cell.playChange.tag = indexPath.row
cell.playChange.addTarget(self, action: #selector(tickClicked), for: .touchUpInside)
cell.tapAction = { (cell) in
// self.player = self.setupAudioPlayerWithFile(file: "https:---.com" + modalsF[indexPath.row].UrlName! as NSString, type: "mp3")
self.avplayer = self.pl(file: "https:---.com" + modalsF[indexPath.row].UrlName! as NSString)
// self.play(tableView.indexPath(for: cell)!.row)
}
return cell
}
func tickClicked(_ sender: UIButton!) {
print(sender.tag)
let cellTop = tableView.cellForRow(at: NSIndexPath(row: sender.tag, section: 0) as IndexPath) as!TableViewCellAudioList
if boolValue == false{
cellTop.playChange.setImage(UIImage(named:"Pause.png"), for: UIControlState.normal)
boolValue = true
} else {
cellTop.playChange.setImage(UIImage(named:"Play.png"), for: UIControlState.normal)
boolValue = false
}
}
func pl(file:NSString) -> AVPlayer? {
let url = URL(string: file as String)
let avPlayer: AVPlayer?
let playerItem = AVPlayerItem(url: url!)
avPlayer = AVPlayer(playerItem:playerItem)
if avPlayer?.rate == 0 {
avPlayer?.play()
avPlayer?.rate = 1.0
} else if avPlayer?.rate == 1{
avPlayer?.pause()
}
return avPlayer
}
TableViewCell:
class TableViewCellAudioList: UITableViewCell {
@IBOutlet weak var number: UILabel!
@IBOutlet weak var name: UILabel!
@IBOutlet weak var duration: UILabel!
@IBOutlet weak var playChange: UIButton!
var tapAction: ((UITableViewCell) -> Void)?
@IBAction func playAudio(_ sender: Any) {
tapAction?(self)
}
}
编辑:
我想速度变慢的问题是您以相同的点击方式开始播放。在创建 AVAudioPlayer
实例之前,您在内存中读取了整个文件。这很慢,很可能是您速度变慢的原因。
您不需要将文件加载到内存中,您可以从文件中播放 - docs。我不是 100% 确定 AVAudioPlayer 是如何在内部工作的,但它可能会减少你的减速。
为了消除减速,您可以在单独的线程中开始播放,或者尝试使用
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 /*seconds*/, execute: {
从当前运行循环周期推迟播放。这应该允许 UIKit 完成所有重绘操作,您应该可以快速更改。 在 之后调度可能是一种快速而肮脏的解决方案,但您需要实际测量开始播放时的减速程度,并决定是否可以将其保留在主线程中。
编辑:在评论中讨论并意识到您不是从磁盘而是从互联网加载文件。
您可能想看看 AVPlayer 而不是 AVAudioPlayer。您的问题是您从 Internet 加载整个文件,这在主线程中 VERY 很慢。 AVPlayer 允许通过 "streaming" 播放远程文件。有了它,您就不必等待整个文件下载。
另一个选项是预下载文件,但这不在本题的讨论范围内。
更改以下方法,需要一些时间才能播放
func tickClicked(_ sender: UIButton!) {
print(sender.tag)
// add me on linkdin from vibha singh for further help
let cellTop = tableView.cellForRow(at: NSIndexPath(row: sender.tag, section: 0) as IndexPath) as!TableViewCellAudioList
// Check for current status of button selection
let checkSelectedStatus = modalsF[sender.tag].isSelected
let currentag = sender.tag
if(checkSelectedStatus == "0")
{
modalsF[sender.tag].isSelected = "1"
avPlayer?.cancelPendingPrerolls()
let _ = avPlayer?.addPeriodicTimeObserver(forInterval: CMTime(seconds: 0.1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: DispatchQueue.main)
{ [] (time) in
// update slider
let duration = CMTimeGetSeconds((avPlayer?.currentItem!.asset.duration)!)
let someVal : Float = Float(CMTimeGetSeconds(time)) / Float(duration)
modalsF[currentag].BarProgressVal = someVal
print("Some val \(someVal)")
print("Current tag \(currentag)")
self.tableView.reloadData()
}
// If 0 then set 1 so that while table scroll it will not change value
cellTop.playChange.setImage(UIImage(named:"Pause.png"), for: UIControlState.normal)
} else
{
modalsF[sender.tag].isSelected = "0" //If 1 then set 0 so that while table scroll it will not change value
cellTop.playChange.setImage(UIImage(named:"Play.png"), for: UIControlState.normal)
}
// this will play at a time one audio
if(lastSelectedcount != 40000 && lastSelectedcount != sender.tag) {
modalsF[lastSelectedcount].isSelected = "0"
}
self.tableView.reloadData()
}