2017-10-28 86 views
0

我对Swift很陌生,已经在这里学习了很多东西。在Swift 4中使用日期()的加计数和递减计时器应该在一段时间后停止

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

现在两个计时器都应该在半场结束时自动停止,以便我可以启动第三个超时计时器。到目前为止,定时器的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() 
} 
+0

您不能有负的时间间隔。那意味着计时器在过去会发射1秒?! – Paulw11

+0

您可以在startTime等于countTime的情况下执行此操作,然后您可以启动第三个加班计时器。 –

回答

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" 
} 

} 
相关问题