Добавление нескольких таймеров обратного отсчета в UICollectionView - PullRequest
0 голосов
/ 25 апреля 2018

Моя цель - иметь уникальный (чч: мм: сс) обратный отсчет timer для каждого заполненного uicollectionviewcell в пределах uicollectionview.

Ниже приведен (сокращенно) код, которым я былвозможность компилирования, но я застрял на том, чтобы заставить его действительно работать в любом качестве ... любое руководство будет оценено.

class VC: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

var timer = Timer()
var secondsRemaining: Int?

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! ExampleCollectionViewCell    

    let expirationDate = Calendar.current.date(byAdding: .hour, value: 24, to: startDate)
    secondsRemaining = expirationDate?.seconds(from: startDate)

    timer = Timer(timeInterval: 1, target: self, selector: #selector(countdown), userInfo: nil, repeats: true)

    return cell
}

    @objc func countdown() {
    secondsRemaining = secondsRemaining! - 1
    if secondsRemaining == 0 {
        print("CELL TIME HAS EXPIRED!")
        timer.invalidate()
    } else {
        let hours = secondsRemaining! / 3600
        let minutes = (secondsRemaining! % 3600) / 60
        let seconds = (secondsRemaining! % 3600) % 60
        let countdownLabelString = String(format: "%02d:%02d:%02d", hours, minutes, seconds)

        //i need to take this countdownLabelString and set it to the 
        //countdownLabel.text that is an element of each cell. i tried 
        //doing all of this in the cell subclass, but no luck... 
    }
} 
}

1 Ответ

0 голосов
/ 25 апреля 2018

Ячейки представления коллекции не обновляются постоянно. Если вы хотите, чтобы они обновились, вы должны сказать им обновить.

Если вы хотите, чтобы в каждой ячейке отображалось различное количество оставшегося времени, вам нужна модель данных, которая сохраняет отдельный expirationDate для каждого отображаемого indexPath. Если ваше представление коллекции представляет собой простой одномерный список элементов, например табличное представление, то вы можете просто использовать одномерный массив. Если представление вашей коллекции отображает сетку ячеек, вам может понадобиться двухмерный массив объектов модели.

Каждый раз, когда вы добавляете элемент в модель данных, включайте значение expirationDate. (Date, когда этот предмет истекает.)

Затем ваш таймер будет вызывать метод представления коллекции reloadData при каждом запуске.

В вашем методе collectionView(collectionView:cellForItemAt:) используйте indexPath, чтобы выяснить, какой элемент в вашей модели данных вы отображаете. Найдите expirationDate для этого indexPath, рассчитайте время, оставшееся с этого момента до истечения срока действия, и отобразите эту информацию в ячейке. (Используйте метод Calendar dateComponents(_:from:to:), чтобы вычислить количество часов, минут и секунд между текущей датой и датой истечения срока действия.)

EDIT

НЕ уменьшать счетчик каждый раз, когда срабатывает таймер. Посчитайте разницу между датой истечения срока и текущей датой, используя dateComponents(_:from:to:)

РЕДАКТИРОВАТЬ # 2:

Ниже приведен пример контроллера представления коллекции, который делает что-то вроде того, что вы хотите:

import UIKit

private let reuseIdentifier = "aCell"

class DatesCollectionVC: UICollectionViewController {

    weak var timer: Timer?
    var dates: [Date] = []
    lazy var componentsFormatter: DateComponentsFormatter = {
        let formatter = DateComponentsFormatter()
        formatter.allowedUnits = [.hour, .minute, .second]
        return formatter
    }()


    override func viewDidLoad() {

        super.viewDidLoad()

        for _ in 1...100 {
            let interval = Double(arc4random_uniform( 10000)) + 120
            dates.append(Date().addingTimeInterval(interval))
        }

        timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
            self.collectionView?.reloadData()
        }
    }

    // MARK: - UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dates.count
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as? MyCell else {
            return UICollectionViewCell()
        }

        let now = Date()
        let expireDate = dates[indexPath.row]
        guard  expireDate > now else {
            cell.intervalLabel.text = "00"
            return cell
        }

        let desiredComponents: Set<Calendar.Component> = [.hour, .minute, .second]
        let components = Calendar.current.dateComponents(desiredComponents, from: now, to: expireDate)
        cell.intervalLabel.text = self.componentsFormatter.string(from: components)

        return cell
    }
}

Код выше выглядит следующим образом:

enter image description here

...