具有Swift 4中的Date()的递增计数和递减计时器应在一段时间后停止

时间:2017-10-28 10:16:47

标签: ios swift date timer

我对Swift很陌生,并且已经使用这里的问题学到了很多东西。

在我的第一个项目中,我尝试编写一个足球游戏时间计时器应用程序。按下哨子按钮后,第一个计时器正在计时,显示播放的分钟数,第二个计时器正在倒计时,显示剩余的分钟数。这项工作到目前为止。

现在两个计时器应该在半场结束时自动停止,这样我就可以启动第三个加时计时器。到目前为止,计时器的invalidate语句不起作用 - 两个计时器都在继续运行。我的if语句似乎有问题,但目前我不知道是什么。所以任何帮助都将非常感激。

var countUpClock: Timer?
var countDownClock: Timer?

private var formatter: DateComponentsFormatter = {
    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .positional
    formatter.allowedUnits = [.minute, .second]
    formatter.zeroFormattingBehavior = .pad
    return formatter
}()

func runPlaytimeClocks() {

    let startTime = Date()
    let countTime = Date() + 2700 //45min of playtime

    if startTime <= countTime {
        countUpClock = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
        self?.timePlayed.text = self?.formatter.string(from: startTime, to: Date())
        }
    }
    else {
        countUpClock?.invalidate()
        }


    if startTime <= countTime {
        countDownClock = Timer.scheduledTimer(withTimeInterval: -1.0, repeats: true) { [weak self] _ in
            self?.timetoPlay.text = self?.formatter.string(from: Date(), to: countTime)
            }
        }
    else {
        countDownClock?.invalidate()
}

1 个答案:

答案 0 :(得分:0)

非常感谢您的回复。

我在这里找到了我想要的内容:http://ioscake.com/swift-nstimer-in-background.html

我将解决方案改为我的时钟(CountUpClock,CountDownClock,OvertimeClock,HalftimeClock)。

你有什么建议什么是开始足球比赛的下半场的最佳解决方案?

到目前为止,当我在半场休息后按下哨子按钮时,CountUpClock再次在0:00开始。但它应该从分钟45:00到90:00运行 - 而CountDownClock应该从45:00再次倒计时到0:00。

这种行为的最佳解决方案是什么?

import UIKit
import UserNotifications

private let stopTimeKey = "stopTimeKey"

class ViewController: UIViewController {

//Outlets
@IBOutlet weak var timePlayed: UILabel!
@IBOutlet weak var timeToPlay: UILabel!
@IBOutlet weak var overtime: UILabel!
@IBOutlet weak var halftime: UILabel!
@IBOutlet weak var halftimeButton: UIButton!

private var stopTime: Date?

override func viewDidLoad() {
    super.viewDidLoad()

    registerForLocalNotifications()

    stopTime = UserDefaults.standard.object(forKey: stopTimeKey) as? Date
    if let time = stopTime {
        if time > Date() {
            startTimers(time, includeNotification: false)
        } else {
            notifyTimerCompleted()
        }
    }
}

private func registerForLocalNotifications() {
    if #available(iOS 10, *) {
           UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
            guard granted && error == nil else {
                // display error
                print("\(String(describing: error))")
                return
            }
        }
    } else {
        let types: UIUserNotificationType = [.badge, .sound, .alert]
        let settings = UIUserNotificationSettings(types: types, categories: nil)
        UIApplication.shared.registerUserNotificationSettings(settings)
    }
}
//Actions
@IBAction func whistleButtonTapped(_ sender: UIButton) {
    overtimeClock?.invalidate()
    overtimeClock = nil
    halftimeClock?.invalidate()
    halftimeClock = nil
    overtime.text = "00:00"
    halftime.text = "00:00"
    halftimeButton.isHidden = true
        //add 10 seconds per halftime to try out
        let time = Date() + 10
        if time > Date() {
            startTimers(time)
        } else {
            timeToPlay.text = "error"
        }
    }

@IBAction func halftimeButton(_ sender: UIButton) {
    halftimeButtoPressed()
}

// Code for different Timers

private var countDownClock: Timer?
private var countUpClock: Timer?
var overtimeClock: Timer?
var halftimeClock: Timer?

private func startTimers(_ stopTime: Date, includeNotification: Bool = true) {
    // save `stopTime` in case app is terminated

    UserDefaults.standard.set(stopTime, forKey: stopTimeKey)
    self.stopTime = stopTime

    // start Timer

    countDownClock = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(handleCountDownTimer(_:)), userInfo: nil, repeats: true)

    countUpClock = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(handleCountUpTimer(_:)), userInfo: nil, repeats: true)

    guard includeNotification else { return }

    // start local notification (so we're notified if timer expires while app is not running)

    if #available(iOS 10, *) {
        let content = UNMutableNotificationContent()
        content.title = "Overtime is starting soon"
        content.body = "In 5 seconds the overtime will start"
        content.sound = UNNotificationSound.default()
        //5 seconds warning before overtime starts
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: stopTime.timeIntervalSinceNow - 5, repeats: false)
        let notification = UNNotificationRequest(identifier: "timer", content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(notification)
    } else {
        let notification = UILocalNotification()
        //5 seconds warning before overtime starts
        notification.fireDate = stopTime - 5 
        notification.alertBody = "Overtime is starting soon"
        UIApplication.shared.scheduleLocalNotification(notification)
    }
}

private func stopTimer() {
    countDownClock?.invalidate()
    countDownClock = nil
    countUpClock?.invalidate()
    countUpClock = nil
}

private func halftimeButtoPressed() {
    overtimeClock?.invalidate()
    overtimeClock = nil
    startHalftimeClock()
    halftimeButton.isHidden = true
}

private let dateComponentsFormatter: DateComponentsFormatter = {
    let _formatter = DateComponentsFormatter()
    _formatter.allowedUnits = [.minute, .second]
    _formatter.unitsStyle = .positional
    _formatter.zeroFormattingBehavior = .pad
    return _formatter
}()

@objc func handleCountDownTimer(_ timer: Timer) {
    let now = Date()

    if stopTime! > now {
        timeToPlay.text = dateComponentsFormatter.string(from: now, to: stopTime!)
    } else {
        stopTimer()
        notifyTimerCompleted()
        startOvertimeClock()
        halftimeButton.isHidden = false
    }
}

@objc func handleCountUpTimer(_ timer: Timer) {
    //add 10 seconds per halftime to try out
    let now = Date() + 10

    if now > stopTime! {
        timePlayed.text = dateComponentsFormatter.string(from: stopTime!, to: now)
    } else {
        stopTimer()
        notifyTimerCompleted()
    }
}

//Overtime Clock
@objc func startOvertimeClock() {

    let startOvertime = Date()

    overtimeClock = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in
        self?.overtime.text = self?.dateComponentsFormatter.string(from: startOvertime, to: Date())
    }
}

//Halftime Clock
@objc func startHalftimeClock() {

    let startHalftime = Date()

    halftimeClock = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in
        self?.halftime.text = self?.dateComponentsFormatter.string(from: startHalftime, to: Date())
    }
}

private func notifyTimerCompleted() {
    timeToPlay.text = "End"
    timePlayed.text = "End"
}

}