我在Parse的几个对象中查询createdAt
日期。我想创建一个24小时(或48/72等)countDown计时器,它从创建对象到24小时后倒计时。 (然后我也将其格式化,并将其显示在单元格UILabel上。)
示例:如果一个对象是在19:34:33创建的,我希望它在此之后24小时到期(或者在创建它之后指定多少小时)。最终在UILabel上显示物品到期前的剩余时间。
目前,我在创建时检索,使其从创建时开始重复倒计时。
但是,我想制作逻辑,以便在创建对象时生成逻辑,然后显示在24小时或48小时,72小时等之前剩余的小时数。
编辑
感谢@pulsar,我在下面的描述中添加了几行代码。现在的问题是我只能检索并正确计算1对象的createdAt日期和时间,因为 仅 查询第一个对象,使所有其他对象具有相同的expiration countDown计时器在它们各自的indexPath.row中作为Parse中的第一个对象。
我无法弄清楚如何添加所有对象,以便它们都有自己的expiresAt函数触发的countDown到期时间。
以下是我如何查询并格式化它(在 viewDidLoad 中): 这是我问的问题,帮我格式化日期:Swift countDown timer Logic
请参阅代码中的评论!
var createdAt = object.createdAt
if createdAt != nil {
//assuming this is where i have to set expiration logic?
let calendar = NSCalendar.currentCalendar()
let comps = calendar.components([.Hour, .Minute, .Second], fromDate: createdAt as NSDate!)
let hours = comps.hour * 3600
let minutes = comps.minute * 60
let seconds = comps.second
//I'm adding these two lines below but not sure what to do with them considering I need to add all the objects to an array that will then display it on indexPath.row(s)
let twentyFourHours = NSTimeInterval(60 * 60 * 24)
self.expiresAt = NSDate(timeInterval: twentyFourHours, sinceDate: object.createdAt!!)
self.timerInt.append(hours + minutes + seconds)
//What do i append to the timerInt array? How can i append the objects while triggering the the expiresAt function?
}
这是我的countDown函数:
func countDown() {
//timerInt is an array where I'm storing the Int values.
for i in 0 ..< timerInt.count {
let hours = timerInt[i] / 3600
//have to somehow add the expiresAt method while looping through each value [i]...?
let minsec = timerInt[i] % 3600
let minutes = minsec / 60
let seconds = minsec % 60
print(String(format: "%02d:%02d:%02d", hours, minutes, seconds))
timerInt[i]--
//Im assuming best practice would be to loop through the values in order to change the values/set the expiration time to each object (the expiresAt method). Any ideas of how and where I can add this in this loop so that it reflects the countDown I want to set?
}
self.tableView.reloadData()
}
最后,对于我的indexPath.row,我正在格式化它并显示如下:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! cell
//I'm formatting the hours, minutes, seconds. However I'm missing the expiresAt function and I have no clue as to where and how to include it... Should it be here or in the countDown() loop?
let hours = timerInt[indexPath.row] / 3600
let minsec = timerInt[indexPath.row] % 3600
let minutes = minsec / 60
let seconds = minsec % 60
myCell.secondLabel.text = String(format: "%02d:%02d:%02d", hours, minutes, seconds)
return myCell
}
关于如何在创建后24/48/72小时将其设置为倒计时的想法?
非常感谢任何和所有帮助!
答案 0 :(得分:1)
Sounds like what you need is to set the expiry date and then get the date components between the current date and the expiry date. Then you can use an NSTimer
to refresh the display. (Don't forget to call NSTimer.invalidate()
when you're done).
An example:
class YourViewController: UIViewController {
var expiresAt: NSDate?
func viewDidLoad() {
// your parse logic here
let twentyFourHours = NSTimeInterval(60 * 60 * 24)
expiresAt = NSDate(timeInterval: twentyFourHours, sinceDate: createdAt)
scheduleTimer()
}
func scheduleTimer() {
NSTimer.scheduledTimerWithTimeInterval(1.0 / 30.0, target: self, selector: "tick:", userInfo: nil, repeats: true)
}
@objc
func tick(timer: NSTimer) {
guard let expiresAt = expiresAt else {
return
}
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
if let components = calendar?.components([.Hour, .Minute, .Second], fromDate: NSDate(), toDate: expiresAt, options: []) {
print(formatDateComponents(components))
}
}
func formatDateComponents(components: NSDateComponents) -> String {
let hours = components.hour
let minutes = components.minute
let seconds = components.second
return "\(hours):\(minutes):\(seconds)"
}
}
You could also make your life much easier by using a structure to store the date components rather than doing that complicated parsing of your timerInt
strings.
struct Time {
let hours: String
let minutes: String
let seconds: String
}
答案 1 :(得分:1)
//: Playground - noun: a place where people can play
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
import UIKit
class MyView: UIView {
weak var l1: UILabel?
weak var l2: UILabel?
weak var l3: UILabel?
let validFor: NSTimeInterval
var validTo: NSDate = NSDate()
lazy var timer: NSTimer = NSTimer(timeInterval: self.validFor, target: self, selector: "done", userInfo: nil, repeats: false)
init(validFor: NSTimeInterval) {
self.validFor = validFor
super.init(frame: CGRect(x: 0, y: 0, width: 500, height: 100))
validTo = timer.fireDate
let ll1 = UILabel(frame: CGRect(x: 1, y: 1, width: 498, height: 30))
ll1.text = "created at: \(NSDate())"
self.addSubview(ll1)
l1 = ll1
let ll2 = UILabel(frame: CGRect(x: 1, y: 33, width: 498, height: 30))
ll2.text = "valid to: \(validTo)"
self.addSubview(ll2)
l2 = ll2
let ll3 = UILabel(frame: CGRect(x: 1, y: 66, width: 498, height: 30))
ll3.text = "valid for next: \(validTo.timeIntervalSinceNow) second"
self.addSubview(ll3)
l3 = ll3
NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// when MyView expires it trigers this function
// and give me a chance to update UI
func done() {
// update UI
dispatch_async(dispatch_get_main_queue(), { [unowned self] () -> Void in
self.l2?.text = " EXPIRED"
self.l3?.text = ""
if let text1 = self.l1?.text,
let text2 = self.l2?.text,
let text3 = self.l3?.text
{
print("")
print(text1, text2, text3)
}
})
}
func updateState() {
// periodically updating UI on request
if timer.valid {
let v = validTo.timeIntervalSinceNow
// update UI
dispatch_async(dispatch_get_main_queue(), { [unowned self] () -> Void in
self.l3?.text = "valid for next: \(v) second"
if let text1 = self.l1?.text,
let text2 = self.l2?.text,
let text3 = self.l3?.text
{
print(text1, text2, text3)
}
})
}
}
}
let c = MyView(validFor: 10.0) // in seconds
let queue = dispatch_queue_create("update", DISPATCH_QUEUE_SERIAL)
// periodic action tu update UI
// in regular intervals
// this is just for demonstration, avoid using use sleep
// in real application
dispatch_async(queue) { () -> Void in
repeat {
c.updateState()
sleep(3)
} while true
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
print("the app is running and responding on user actions")
print("MyView labels are updating 'automatically'\n")
})
print("playground continue ....\n")