我想让它在按下按钮时打开计时器,计算秒数,停止后,再次播放时,它从按下暂停时停止的秒数开始计数。但是现在我没有随着时间的推移而发生变化,尽管按钮上的图像发生了变化。编码:
//MusicViewController
private var second64: Int64?
private var second = TimeInterval()
private var time: String?
//В этом методе мы считаем секунды
@objc private func countSeconds( _ : TimeInterval) -> TimeInterval{
if second > 0.0{
second -= 1.0
second64 = Int64(second)
time = TimeFormatter().convertTimeToString(second64)
}
return second
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//Воспроизводим длительность аудиозаписи в основном потоке
second64 = audio.duration
time = TimeFormatter().convertTimeToString(second64)
var timer = Timer()
if button.title(for: .normal) == "▶️"{
if button.isSelected{
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0){
timer = self.setTimer()
cell.durationLabel.text = self.time
}
}
else if button.title(for: .selected) == "⏸" {
if button.isSelected{
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0){
timer.invalidate()
cell.durationLabel.text = self.time
}
}
}
}
}
else{
cell.singerLabel.text! = ""
cell.titleLabel.text! = ""
}
}
//Метод в протоколе для взаимодействия с презентером.
func setTimer () -> Timer{
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(countSeconds(_:)), userInfo: nil, repeats: true)
print(second)
return timer
}
}
class TimeFormatter{
private var seconds = TimeInterval()
//Метод, преобразующий время в нужный формат
private func timeFormatter (_ : TimeInterval) -> DateComponentsFormatter{
let formatter = DateComponentsFormatter()
// Длительность будет отображаться как 1:00:00
if seconds > 59.59{
formatter.allowedUnits = [.hour, .minute, .second]
}
else{
formatter.allowedUnits = [.minute, .second]
}
formatter.unitsStyle = .positional
formatter.zeroFormattingBehavior = .pad
return formatter
}
//Метод, передающий информацию о длительности записи в приложение
func convertTimeToString(_ number: Int64?) -> String?{
if let unwrappedNumber = number{
seconds = TimeInterval(integerLiteral: unwrappedNumber)
print(seconds)
}
let formatter = timeFormatter(seconds)
let timeString = formatter.string(from: seconds)
return timeString
}
}
UPD。现在我的代码如下所示: //MusicViewController
私有变量索引 = Int()
private var posts: [Post] = []
private var timer: Timer?
private var playingCell: MusicTableViewCell?{
let count = store!.getPostsCount()
for i in 0...count-1{
index = i
let post = store!.getPost(for: index)
posts.append(post)
}
let indexPath = IndexPath(row: index, section: 0)
return tableView.cellForRow(at: indexPath) as? MusicTableViewCell
私有函数重置(){
guard let cell = playingCell, let button = cell.playButton, let post = store?.getPost(for: index), let attachments = post.attachments, let audio = attachments[index].audio else {return}
button.isSelected = false
second64 = audio.duration
cell.second = cell.makeTimeIntervalFromInt(second64)
}
//方法在当前时刻停止音乐 private func pauseMusic() {
guard let cell = playingCell, let playbutton = cell.playButton else {return}
playbutton.isSelected = false
timer?.invalidate()
}
私有变量 second64: Int64? //private let second = TimeInterval(integerLiteral: second64!)
扩展 MusicViewController: UITableViewDataSource, MusicTableViewCellDelegate{
func musicShouldStartPlaying(_ cell: MusicTableViewCell) {
if cell !== playingCell{
musicShouldStopPlaying(cell)
}
cell.playButton.isSelected = true
timer = cell.setTimer()
}
func musicShouldStopPlaying(_ cell: MusicTableViewCell) {
if cell.second == 0.0 || cell !== playingCell{
cell.playButton.isSelected = false
pauseMusic()
reset()
}
else{
cell.playButton.isSelected = false
pauseMusic()
}
cell.playButton.isSelected = false
pauseMusic()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let button = cell.playButton!
button.actions(forTarget: button, forControlEvent: .touchUpInside)
cell.delegate = self
cell.index = indexPath.row
cell.second = cell.makeTimeIntervalFromInt(second64)
}
//MusicTableViewCell
var second64: Int64?
var index: Int!
var second = TimeInterval()
private var time: String?
weak var delegate: MusicTableViewCellDelegate?
func makeTimeIntervalFromInt( _ : Int64?) -> TimeInterval{
if let currentSecond = second64{
second = TimeInterval(integerLiteral: currentSecond)
}
return second
}
//View 与 Presenter 协议 ViewProto 交互的协议:class {
//Метод, вызывающий презентер во View
func setPresenter(_ presenter: PresenterProto)
//Метод, обновляющий посты
func updateData()
// 函数重置()
}
// Presenter 交互协议与 View 协议 PresenterProto: class {
// Метод, вызывающий View в презентере
func viewLoaded(with view: ViewProto)
//Метод, позволяющий узнать количество постов в массиве
func getPostsCount() -> Int
//Показывает содержание конкретного поста
func getPost(for index: Int) -> Post
}
协议 MusicTableViewCellDelegate: class{ func musicShouldStartPlaying(_ cell: MusicTableViewCell)
func musicShouldStopPlaying(_ cell: MusicTableViewCell)
//func reset(_ cell: MusicTableViewCell)
}
'''
这是使用可更新计时器的示例。
添加
您需要在countSeconds
下面的方法中更新时间补充 2
这个任务对我来说似乎很有趣,我完全重写了问题作者的实现,并做了一个测试项目,其中包含切换列表中的条目的逻辑(github)
Первоначально я перенес логику переключения и отслеживания времени в ячейки, однако это оказалось неверным решением из-за повторного использования ячеек при прокрутке и соответственно остановки таймера, работающего в выбранной ячейке, поэтому я сделал общий таймер во вью контроллере, и здесь столкнулся с тем, что обычный
Timer
тоже останавливается при прокрутке, так как запускается в основном цикле событий (main loop).Поэтому я использовал реализацию фонового таймера отсюда
Замечания:
Класс ячейки содержит кнопку переключения и лейбл для вывода времени, внутри управляет переключением кнопки и делегирует события переключения во вью контроллер
视图控制器包含一个表,控制定时器和记录之间的切换