因此,我正在swift中構建一個應用程序,爲不同的任務設置一個長計時器。我希望能夠保存定時器的進度,以便用戶可以離開視圖控制器並稍後再回來。如何保存倒數計時器的進度?
用戶從tableView中選擇一個任務,每個任務都有一定的時間附加到它,並被segued到一個實際的計時器。我希望用戶能夠離開計時器並留下剩餘時間以在我的數據模型中進行更新。
我到目前爲止似乎沒有工作,我不知道該怎麼做。以下代碼供用戶離開計時器並返回表格。 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()
}
此功能時,我去表視圖從定時器(視圖控制器),然後返回到計時器,留在計時器的時間恢復到原來的狀態。
這裏是兩個視圖控制器
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()
}
}
}
上面是的tableView的代碼,下面我會後所述定時器
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.
}
}
我該如何實施? – Tom