2017-07-24 54 views
0

因此,我正在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. 
} 
} 

回答

0

保存TaskData的陣列,並且其相應的開始時間和/或結束時間並將該陣列保存到UserDefaults

+0

我該如何實施? – Tom

1

當您啓動計時器時,將當前日期作爲時間間隔保存到實例變量中:

定義實例變量:

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

這是一個非常粗略的輪廓。你需要弄清細節,但這應該讓你開始。

+0

我已經實現了這一點,這很有幫助,但我現在關心的是剩餘時間不會在用戶退回到表視圖時更改,以便用戶可以從停止的位置開始。這是我想要做的與我的取消按鈕功能。爲了給出一些上下文,您可以選擇一個任務的名稱和您想要處理的小時數,所以當用戶退出應用程序或關閉應用程序時,剩下的時間應該保持不變。 – Tom

+0

好的......上面的代碼概述瞭如何計算剩餘時間。將該值保存到userDefaults,並在應用程序啓動時讀取它。你不瞭解什麼部分? –

+0

嗯,我需要學習如何將內容保存到userDefaults,目前爲止我只使用NSkeyedArchiver – Tom