iOS 电商倒计时
背景
最近项目中,需要做一个如图所示的倒计时控件,上网搜了一圈,发现大家的方法大同小异,都是把倒计时的秒,转换成时分秒然后拼接字符串,见下图
网上大部分采用的方法
juejin.cn/post/684490…
在我的项目中,期望这个倒计时控件的format是可以自定义的,所以计算时分秒这样的方式,对于我的需求是不太灵活的
既然format需要自定义,那么很容易想到一个时间格式处理的类:DateFormatter
思路
后端返回的字段
init_time // 需要倒计时的时长,单位ms
format // 展示的倒计时格式
我们的需求其实非常明确,就是完成一个可以自定义format的倒计时label
那我们拆解一下整个需求:
- 自定format的label
- Date自定义format显示
- 指定Date自定义format显示
- 可以进行倒计时功能
那么我们怎么才能把要倒计时的时长,转换为时分秒呢?
- 直接计算后端给的init_time,算出是多少小时,多少分钟,多少秒
- 如果我从每天的零点开始计时,然后把init_time作为偏移量不就是我要倒计时的时间吗,而且这个可以完美解决需要自定义format的问题,Date可以直接通过 DateFormatter转化成字符串
Date自定义format显示
let df = DateFormatter()
df.dateFormat = "hh:mm:ss"
print("🍀", df.string(from: Date()), "🍀\n\n")
输出:🍀 03:56:28 🍀
指定Date自定义format显示
let df = DateFormatter()
var calendar = Calendar(identifier: .gregorian)
let startOfDate = calendar.startOfDay(for: Date())
df.dateFormat = "hh:mm:ss"
print("🍀", df.string(from: startOfDate), "🍀\n\n")
输出:🍀 12:00:00 🍀
完整功能
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
initCountdownTimer()
return true
}
private var timer: DispatchSourceTimer?
private var second = 0
// 单位ms
var delayTime = 0
// 单位ms
var interval = 1000
var initSecound = 10
var format = "hh:mm:ss"
private lazy var startDate: Date = {
var calendar = Calendar(identifier: .gregorian)
let startOfDate = calendar.startOfDay(for: Date())
return Date(timeInterval: TimeInterval(initSecound), since: startOfDate)
}()
private lazy var df: DateFormatter = {
let df = DateFormatter()
df.dateFormat = format
return df
}()
func initCountdownTimer() {
timer = DispatchSource.makeTimerSource(queue: .main)
timer?.schedule(deadline: .now() + .milliseconds(delayTime), repeating: .milliseconds(interval), leeway: .milliseconds(1))
timer?.setEventHandler { [weak self] in
self?.updateText()
self?.second += 1
}
timer?.resume()
}
func deinitTimer() {
timer?.cancel()
timer = nil
}
func updateText() {
if second == initSecound && second != 0 {
deinitTimer()
}
if second == initSecound {
return
}
let date = Date(timeInterval: -TimeInterval(second + 1), since: startDate)
let text = df.string(from: date)
print(text)
}
输出:
12:00:09
12:00:08
12:00:07
12:00:06
12:00:05
12:00:04
12:00:03
12:00:02
12:00:01
12:00:00
以上整个功能基本完成,但是细心的同学肯定发现了,按道理小时部分应该是00,但是实际是12,这是为什么呢,为什么呢?
我在这里研究了好久,上网查了很多资料
最后去研究了foramt每个字母的意思才知道:
h 代表 12小时制
H 代表 24小时制,如果想要显示00,把"hh:mm:ss"改成"HH:mm:ss"即可
时间格式符号字段详见
作者:xiAo_Ju
链接:https://juejin.cn/post/7240303252930609207
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
链接:https://juejin.cn/post/7240303252930609207
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。