注册
iOS

iOS 电商倒计时

背景


最近项目中,需要做一个如图所示的倒计时控件,上网搜了一圈,发现大家的方法大同小异,都是把倒计时的秒,转换成时分秒然后拼接字符串,见下图


31ff4ec730e2cce33ba7fc9b30e0b989.png


网上大部分采用的方法
juejin.cn/post/684490… 

bc260709371add55f6cb60149a39ee42.png


在我的项目中,期望这个倒计时控件的format是可以自定义的,所以计算时分秒这样的方式,对于我的需求是不太灵活的


既然format需要自定义,那么很容易想到一个时间格式处理的类:DateFormatter


思路


后端返回的字段

init_time // 需要倒计时的时长,单位ms
format // 展示的倒计时格式

我们的需求其实非常明确,就是完成一个可以自定义format的倒计时label


那我们拆解一下整个需求:

  • 自定formatlabel
    • Date自定义format显示
    • 指定Date自定义format显示
  • 可以进行倒计时功能

那么我们怎么才能把要倒计时的时长,转换为时分秒呢?

  • 直接计算后端给的init_time,算出是多少小时,多少分钟,多少秒
  • 如果我从每天的零点开始计时,然后把init_time作为偏移量不就是我要倒计时的时间吗,而且这个可以完美解决需要自定义format的问题,Date可以直接通过 DateFormatter转化成字符串 
5727433ee564b9bf782b7b521fba5561.png


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

0 个评论

要回复文章请先登录注册