gpt4 book ai didi

swift - tableview 单元格上的详细文本标签不会使用倒数计时器刷新

转载 作者:行者123 更新时间:2023-11-28 13:33:36 25 4
gpt4 key购买 nike

我有一个带有基本 cellforrow 函数的表格 View 。我还为我的待办事项列表应用构建了一个计时器功能。

我正在尝试创建一个应用程序,该应用程序使用标准字幕单元格在表格 View 的每个单元格中都有一个正在运行的倒数计时器。计时器名称显示在文本字段中,正在运行的计时器显示在副标题中。

这里的想法是在用户为所选任务设置特定截止日期时计算任务的剩余时间。

我成功地实现了这个功能,但我遇到的问题是,当我将单元格(副标题)的 detailtextlabel 设置为剩余时间(显示剩余天数/小时/分钟/秒)时,它不会刷新。

总而言之,我想创建一个任务的倒计时功能,以显示它每秒倒计时。我希望它在 viewdidload 上加载。

我的计时器正确吗?或在错误的地方。我认为如果它是 inn cellforRow 函数,那么让计时器刷新整个表是有意义的。

我在 cellforrow 函数中尝试了一个计时器,但没有成功。然后我为计时器创建了一个单独的函数来刷新其中包含 reloadData() 的 TableView 。这个函数在 viewDidLoad 中被调用。倒计时和一切正常,但我的标签不会更新,除非我单击一个单元格或添加一个新的待办事项。

override func viewDidLoad() {
super.viewDidLoad()

func startTimer() {
self.countDownTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(reloadTableForTimer), userInfo: nil, repeats: true)
}
}



@objc func reloadTableForTimer() {
DispatchQueue.main.async { self.tableView.reloadData() }
}






override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
if item.done == true {
cell.detailTextLabel?.text = "Complete!"
}else {

var deadlineDatesAll = item.deadlineDate

if deadlineDatesAll == "" {
cell.detailTextLabel?.text = "NO DEADLINE SET"
} else {
// insert code for data disection and then to timer to display each countdown:
retrieveDateComponants(deadlineDateChosen: deadlineDatesAll.description)
var dataComponants:Array = retrieveDateComponants(deadlineDateChosen: deadlineDatesAll.description)

var returnedDueDateString = updateTime(yearExtract: dataComponants[0], monthExtract: dataComponants[1], dayExtract: dataComponants[2], hourExtract: dataComponants[3], minExtract: dataComponants[4], secsExtract: dataComponants[5])
cell.detailTextLabel?.text = "Due In: \(returnedDueDateString)"
}

}
cell.accessoryType = item.done == true ? .checkmark : .none
}else {
cell.textLabel?.text = "No Item Found"
}
return cell
}


//UPDATE countdowns function:
@objc func updateTime(yearExtract:String, monthExtract:String, dayExtract:String,hourExtract:String,minExtract:String, secsExtract:String) -> (String) {

var deadlineTimeDueString : String = ""

let futureDate: Date = {
var future = DateComponents(
year: Int(yearExtract),
month: Int(monthExtract),
day: Int(dayExtract),
hour: Int(hourExtract),
minute: Int(minExtract),
second: Int(secsExtract) )
return Calendar.current.date(from: future)!
}()

var countdownComp: DateComponents {
return Calendar.current.dateComponents([.day, .hour, .minute, .second], from: Date(), to: futureDate)
}

let countdown = countdownComp //only compute once per call
let days = countdown.day!
let hours = countdown.hour!
let minutes = countdown.minute!
let seconds = countdown.second!

print((String(format: "OUTPUT TEST: %02d:%02d:%02d:%02d", days, hours, minutes, seconds)))

if seconds < 0 {
deadlineTimeDueString = String("OVERDUE")
} else if seconds > 0 {
deadlineTimeDueString = String(format: "%02d Days, %02d Hours, %02d Mins & %02d Secs", days, hours, minutes, seconds)
}
return deadlineTimeDueString
}


一切正常,除了倒计时时间不会刷新标签,除非我手动单击另一个单元格或同一个单元格。剩余时间工作并且每秒更新一次。

任何帮助将不胜感激感谢 MFK

最佳答案

我可能建议让单元格更新自己的标签,但为了让它们同时更新所有标签,让 Controller 在单元格应该更新时发布通知。

因此,您可以为计时器创建一个通知:

extension Notification.Name {
static let timerFired = Notification.Name(rawValue: Bundle.main.bundleIdentifier! + ".timer")
}

然后 View Controller 会发布这个通知:

class ViewController: UITableViewController {
var todos = ...

private weak var timer: Timer?

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
NotificationCenter.default.post(name: .timerFired, object: nil)
}
}

override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
timer?.invalidate()
}
}

然后 UITableViewDataSource 可以将“待办事项”传递给单元格:

// MARK: - UITableViewDataSource

extension ViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return todos.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ToDoCell", for: indexPath) as! ToDoCell
cell.configure(for: todos[indexPath.row])
return cell
}
}

然后单元格可以将所有这些联系在一起,观察通知并适本地更新文本:

class ToDoCell: UITableViewCell {
private var todo: ToDo?
private var token: NSObjectProtocol?

private static let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.allowedUnits = [.day, .hour, .minute, .second]
formatter.maximumUnitCount = 2
return formatter
}()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
addObservers()
}

required init?(coder: NSCoder) {
super.init(coder: coder)
addObservers()
}

deinit {
removeObservers()
}

func configure(for todo: ToDo) {
self.todo = todo
textLabel?.text = todo.name
if todo.done {
removeObservers()
detailTextLabel?.textColor = .black
detailTextLabel?.text = "Done!"
accessoryType = .checkmark
} else {
addObservers()
updateTime()
accessoryType = .none
}
}
}

private extension ToDoCell {
func addObservers() {
guard token == nil else { return }

token = NotificationCenter.default.addObserver(forName: .timerFired, object: nil, queue: .main) { [weak self] _ in
self?.updateTime()
}
}

func removeObservers() {
if let token = token {
NotificationCenter.default.removeObserver(token)
}
}

func updateTime() {
guard let date = todo?.deadline else {
detailTextLabel?.text = "No deadline specified"
detailTextLabel?.textColor = .black
return
}

let now = Date()
if date < now {
detailTextLabel?.text = "Past due " + (ToDoCell.formatter.string(from: date, to: now) ?? "")
detailTextLabel?.textColor = .red
} else {
detailTextLabel?.text = ToDoCell.formatter.string(from: now, to: date)
detailTextLabel?.textColor = .black
}
}
}

请注意,我使用 DateComponentsFormattermaximumUnitCount2,这样我就不会看到烦人的细节级别。因此,我只会看到“7 天 12 小时”而不是“7 天 12 小时 42 分钟 8 秒”,但它会显示秒数可能相关的位置(例如不到 1 小时):

enter image description here

但细节不如将大量特定于单元格的代码拉入 UITableViewCell 子类而不是将其放在 View Controller 中的一般设计原则重要。

关于swift - tableview 单元格上的详细文本标签不会使用倒数计时器刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56993074/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com