背景
最近项目中,需求做一个如图所示的倒计时控件,上网搜了一圈,发现大家的办法迥然不同,都是把倒计时的秒,转化成时分秒然后拼接字符串,见下图
网上大部分采用的办法 /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”即可