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
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。