上篇博客我跟大家分享了如何在iOS系統(tǒng)中使用原生框架獲取步數(shù),又是大半個月過去了,運動模塊的全部功能也總算完成了,也打算有始有終的把如何做一個跑步類App跟大家分享了。
運動類應用中,有一個很重要的模塊就是計時器,當然,這個計時器不算復雜,只要有簡單的開始、暫停以及復位功能即可。那么今天我們從Model層來看看這個計時器的邏輯實現(xiàn)。
我們先自己創(chuàng)建一個時間的Model
class RunningTimer: NSObject {
//MARK: var property
private var timeLabel: UILabel!
private var timer: NSTimer?
//開始和結(jié)束時間列表
lazy private var startTimes = [NSDate]()
lazy private var endTimes = [NSDate]()
internal var timeNumber = 0 {
didSet {
timeString = getTimeStringFromSecond(timeNumber)
}
}
internal private(set) var timeString = "00:00:00" {
didSet {
timeLabel.text = timeString
}
}
}
先從這段聲明變量的代碼分析開來,首先是定義了一個timeLabel,這個變量主要是為了在初始化時,直接將View層要顯示的Label綁定進來,timer即為一個計時器,順便定義了兩個數(shù)組,用來記錄時間,因為在真實環(huán)境中,可能有若干次暫停,所以用數(shù)組來存儲。timeNumber即為計時器中的總秒數(shù),用Swift的didSet特性來監(jiān)聽屬性的變化,當秒數(shù)發(fā)送變化時,講秒數(shù)轉(zhuǎn)化成時間的標準格式,并且賦值給timeString,同理,timeString也在屬性發(fā)送變化時,將自己的值賦值給Label的text屬性用以顯示。
到這里我們的變量講解完畢,接著往下看功能的實現(xiàn)。
//MARK: - 初始化
init(timeLabel: UILabel) {
self.timeLabel = timeLabel
timeLabel.text = timeString
}
這是這個Model的初始化,用意一目了然,傳入一個外部Label用以顯示時間。
//計時開始
func timingStart(){
startTimes.append(NSDate())
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(self.count), userInfo: nil, repeats: true)
}
//暫停計時
func timingPause(){
endTimes.append(NSDate())
timer?.invalidate()
}
//暫停后繼續(xù)計時
func timingContinue(){
timingStart()
}
//重置Timer
func resetToStart() {
startTimes = []
endTimes = []
timer?.invalidate()
timeNumber = 0
}
這里定義了四個方法,對應我們UI界面會出現(xiàn)的Button功能,Start、Pause、Continue、resetToStart。代碼很簡單,當start時添加當前時間至數(shù)組里,并且啟動定時器,暫停時,銷毀定時器,添加暫停的時間進入暫停數(shù)組。繼續(xù)和重置同理。那么我們來看定時器啟動時,對應的selector做了哪些事情。
//MARK: - 計時器
private func timeCount(){
if startTimes.count == 1 {
let currentTime = NSDate()
timeNumber = Int(CFDateGetTimeIntervalSinceDate(currentTime, startTimes[0]))
}else{
if startTimes.count - endTimes.count == 1 {
endTimes.append(NSDate())
}
let index = startTimes.count - 1
endTimes[index] = NSDate()
var timeCount = 0
for startTime in startTimes{
timeCount += Int(CFDateGetTimeIntervalSinceDate(endTimes[startTimes.indexOf(startTime)!],startTime))
}
timeNumber = timeCount
}
}
@objc private func count(){
timeCount()
}
當計時器的count()方法運行時、調(diào)用timeCount()方法。
當我們第一次運行計時器時,獲取的秒數(shù)就是開始時間與當前時間比對的差值。
而之后,就是跟暫停之后啟動時間的對比了。
這里面使用public func CFDateGetTimeIntervalSinceDate(theDate: CFDate!, _ otherDate: CFDate!) -> CFTimeInterval函數(shù)獲取兩個時間之間的時間戳差值。
最后再把前面那個秒數(shù)轉(zhuǎn)格式化時間的方法也貼出來吧。
//從以秒計時的時間里獲得表示時間的字符串用于顯示
func getTimeStringFromSecond(seconds: Int) -> String {
let secondNumber = seconds % 60
let minuteNumber = (seconds / 60) % 60
let hourNumber = (seconds / (60*60)) % 24
let secondText = secondNumber < 10 ? "0\(secondNumber)" : "\(secondNumber)"
let minuteText = minuteNumber < 10 ? "0\(minuteNumber)" : "\(minuteNumber)"
let hourText = hourNumber < 10 ? "0\(hourNumber)" : "\(hourNumber)"
return "\(hourText):\(minuteText):\(secondText)"
}