如何保存倒数计时器的进度?



所以我正在用swift构建一个应用程序,为不同的任务设置一个长计时器。我希望能够保存计时器的进度,以便用户可以离开视图控制器并稍后返回它。

用户从 tableView 中选择一个任务,每个任务都附加了一定时间量,并被隔离到实际计时器。我希望用户能够离开计时器,并在我的数据模型中保留剩余的更新时间。

到目前为止,我所拥有的似乎不起作用,我不确定该怎么办。下面的代码供用户离开计时器并返回到表中。TaskData是我的数据模型。

@IBAction func cancel(_ sender: Any) {
let item = TaskData()
item.time = String(seconds)
dismiss(animated: true, completion: nil)
delegate?.viewController(self, didFinishEditing: item)
}

在我的表视图控制器中,我在下面使用此功能

func viewController(_ controller: ViewController, didFinishEditing item: TaskData) {
if let index = tasks.index(of: item) {
let indexPath = IndexPath(row: index, section: 0)
if let cell = tableView.cellForRow(at: indexPath) {
configureText(for: cell, with: item)
}
}
dismiss(animated: true, completion: nil)
saveTasklistItems()
}

当我从计时器(ViewController(转到表视图,然后返回到计时器时,计时器中剩余的时间将恢复为原来的时间。

这是两个视图控制器的代码

import UIKit
class TaskListViewController: UITableViewController, 
AddNewTaskViewControllerDelegate, TimerViewControllerDelegate {
var tasks: [TaskData]
required init?(coder aDecoder: NSCoder) {
tasks = [TaskData]()
super.init(coder: aDecoder)
loadChecklistItems()
}

//DELEGATE PROTOCOLS
func addNewTaskViewControllerDidCancel(_ controller: AddNewTaskViewController) {
dismiss(animated: true, completion: nil)
}
func addNewTaskViewController(_ controller: AddNewTaskViewController, didFinishAdding item: TaskData) {
let newRowIndex = tasks.count
tasks.append(item)
print(item.time)
let indexPath = IndexPath(row: newRowIndex, section: 0)
let indexPaths = [indexPath]
tableView.insertRows(at: indexPaths, with: .automatic)
dismiss(animated: true, completion: nil)
saveTasklistItems()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "AddTask" {
let navigationController = segue.destination as! UINavigationController
let controller = navigationController.topViewController as! AddNewTaskViewController
controller.delegate = self
} else if segue.identifier == "ShowTimer" {
let navigationController = segue.destination as! UINavigationController
let controller = navigationController.topViewController as! ViewController
if let indexPath = tableView.indexPath(for: sender as! UITableViewCell) {
controller.timerTask = tasks[indexPath.row]
controller.timerTime = tasks[indexPath.row]
}
}
}
func viewController(_ controller: ViewController, didFinishEditing item: TaskData) {
if let index = tasks.index(of: item) {
let indexPath = IndexPath(row: index, section: 0)
if let cell = tableView.cellForRow(at: indexPath) {
configureText(for: cell, with: item)
}
}
dismiss(animated: true, completion: nil)
saveTasklistItems()
}
///////////////////////////////
func configureText(for cell: UITableViewCell, with item: TaskData) {
let label = cell.viewWithTag(2) as! UILabel
label.text = item.time
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
tasks.remove(at: indexPath.row)
let indexPaths = [indexPath]
tableView.deleteRows(at: indexPaths, with: .automatic)
saveTasklistItems()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tasks.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskListItem", for: indexPath)
let taskItem = tasks[indexPath.row]
let label = cell.viewWithTag(1) as! UILabel
let label2 = cell.viewWithTag(2) as! UILabel
label.text = taskItem.task
label2.text = taskItem.time
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
//SAVE FUNCTIONALITY
func documentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}
func dataFilePath() -> URL {
return documentsDirectory().appendingPathComponent("Tasklists.plist")
}
func saveTasklistItems() {
let data = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWith: data)
archiver.encode(tasks, forKey: "TasklistItems")
archiver.finishEncoding()
data.write(to: dataFilePath(), atomically: true)
}
func loadChecklistItems() {
let path = dataFilePath()
if let data = try? Data(contentsOf: path) {
let unarchiver = NSKeyedUnarchiver(forReadingWith: data)
tasks = unarchiver.decodeObject(forKey: "TasklistItems") as! [TaskData]
unarchiver.finishDecoding()
}
}
}

上面是表格视图,下面我将发布计时器

import UIKit
protocol TimerViewControllerDelegate: class {
func viewController(_ controller: ViewController, didFinishEditing item: TaskData)
}
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var timerLabel: UILabel!
@IBOutlet weak var pauseButton: UIButton!
@IBOutlet weak var startButton: UIButton!
@IBOutlet weak var timerTaskName: UILabel!
@IBOutlet weak var timerTimeSetting: UILabel!
@IBOutlet weak var progressView: UIProgressView!
weak var delegate: TimerViewControllerDelegate?
var timerTask: TaskData?
var timerTime: TaskData?
var seconds: Int = 0
var timer = Timer()
var isTimerRunning = false
var resumeTapped = false
var progressViewSpeed: Double = 0.0
//THIS BUTTON CREATS AN UPDATED TASK DATA TIME MEMBER
@IBAction func cancel(_ sender: Any) {
let item = TaskData()
item.time = String(seconds)
print(item.time)
dismiss(animated: true, completion: nil)
delegate?.viewController(self, didFinishEditing: item)
}
/////////////////////////////

@IBAction func startButtonTapped(_ sender: Any) {
if isTimerRunning == false {
runTimer()
self.startButton.isEnabled = false
}
if seconds >= (500 * 60 * 60) {
seconds = (500 * 60 * 60)
}
}
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(ViewController.updateTimer)), userInfo: nil, repeats: true)
isTimerRunning = true
pauseButton.isEnabled = true
}
@IBAction func pauseButtonTapped(_ sender: UIButton) {
if self.resumeTapped == false {
timer.invalidate()
self.resumeTapped = true
self.pauseButton.setTitle("Resume",for: .normal)
} else {
runTimer()
self.resumeTapped = false
self.pauseButton.setTitle("Pause",for: .normal)
}
}
/*
@IBAction func resetButtonTapped(_ sender: Any) {
timer.invalidate()
seconds = 60
self.timerLabel.text = timeString(time: TimeInterval(seconds))
if self.resumeTapped == true {
self.resumeTapped = false
self.pauseButton.setTitle("Pause",for: .normal)
}
isTimerRunning = false
pauseButton.isEnabled = false
startButton.isEnabled = true
}
*/
func updateTimer() {
if seconds < 1 {
timer.invalidate()
//Send alert to indicate "time's up!"
} else {
seconds -= 1
timerLabel.text = timeString(time: TimeInterval(seconds))
}
progressViewSpeed = 1 / Double(seconds)
progressView.progress += Float(progressViewSpeed)
}
func timeString(time:TimeInterval) -> String {
let hours = Int(time) / 3600
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i:%02i", hours, minutes, seconds)
}
override func viewDidLoad() {
super.viewDidLoad()
pauseButton.isEnabled = false
if let task = timerTask {
timerTaskName.text = task.task
}
if let timerTimeLeft = timerTime {
timerTimeSetting.text = timerTimeLeft.time
}
//I SOLVED A SERIOUS ERROR HERE
let timeLeft: Int? = Int(timerTimeSetting.text!)
seconds = Int(timeLeft!) * 60 * 60
self.timerLabel.text = timeString(time: TimeInterval(seconds))
///////////////////////////////
self.progressView.transform = CGAffineTransform.identity.rotated(by: CGFloat.pi / 2).scaledBy(x: 1, y: 150)

}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

启动计时器时,将当前日期作为时间间隔保存到实例变量中:

定义实例变量:

var startTime: TimeInterval = 0.0
var elapseTime: TimeInterval = 0.0
let totalTime = 100.0 //Replace with your desired total time
weak var timer: Timer?

然后,您可以使用如下代码:

@IBAction func startButtonTapped(_ sender: Any) {
//save the current date as a time interval
startTime = Date().timeIntervalSinceReferenceDate
timer = Timer.scheduledTimer(timeInterval: 1, 
target: self, 
selector: #selector(ViewController.updateTimer), 
userInfo: nil, 
repeats: true)
}
@IBAction func pauseTimer(_ sender: Any) {
timer.invalidate()
//Calculate the amount of time that's passed since starting the timer
elapsedTime = Date().timeIntervalSinceReferenceDate - startTime
//Calculate the amount of time remaining
timeRemaining = totalTime - elapsedTime
//Save timeRemaining to UserDefaults or do whatever you desire with it.
}

这是一个非常粗略的轮廓。您需要弄清楚细节,但这应该可以让您开始。

保存 TaskData 数组及其相应的开始时间和/或结束时间,并将该数组保存到 UserDefaults

最新更新