Would you please help me? :) I've been struggling with this problem for like a week and couldn't solve it. my problem is - I can't pass data between my two view controllers, let me explain myself better: I've got one VC which is the main VC that has the Clock animation, and I've got another VC which takes care of the SettingsVC. now no matter what I do (delegation, anything..) it doesn't let me to pass my UILabel's text to the main VC. I beg for a help since I can't keep going with my app and I'm about to finish it.
MyCode: 1st ViewController:
import UIKit
import CircleProgressView
import AVFoundation
import Foundation
import PickerViewCell
class PomodoroViewController: UIViewController{
//MARK: - Outlets Section:
@IBOutlet weak var playSymbol: UIButton!
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var settingsSymbol: UIBarButtonItem!
@IBOutlet weak var timeLabel: UILabel!
@IBOutlet weak var deleteTask: UIButton!
@IBOutlet weak var tasksLabel: UILabel!
@IBOutlet weak var circleProgressView: CircleProgressView!
// MARK: - Class Variables
private var timerIsOn = false
var timeRemaining = 1500
private var totalTime = 1500
private var completedTasks = 0
private var secondsPassed = 0 // AINT SURE
private var counter = 0
//Instance objects:
private var timer = Timer()
var calculateManager = CalculateManager()
//MARK:- ViewDidLoad Section:
override func viewDidLoad() {
textField.delegate = self
deleteTask.isHidden = true
}
//MARK: - Play Function:
@IBAction func playPreesedButton(_ sender: UIButton) {
//What will happen once we hit the play button:
counter += 1 //1 = play, 2 = pause, 3 = play, 4 = pause
if !timerIsOn
{ // means its true cause the user pressed the play button:
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(onTimerFires), userInfo: nil, repeats: true)
timerIsOn = true
deleteTask.isHidden = false // showing up the delete button.
}
playSymbol.setBackgroundImage(UIImage(named: T.P.pausePic), for: .normal) // setting the image to pause button
if counter.isMultiple(of: 2) {
timer.invalidate()
timerIsOn = false // cause we stopped the timer due to the Pause Button.
playSymbol.setBackgroundImage(UIImage(named: T.P.playPic), for: .normal) // setting the image to play button
}
}
//MARK: - Update Function:
@objc func onTimerFires()
{
print("the total time is - \(timeRemaining)")
timeRemaining -= 1 //1499 - in seconds
secondsPassed = totalTime - timeRemaining
//Updating the timeLabel:
let minutesLeft = Int(timeRemaining) / 60 % 60
let secondsLeft = Int(timeRemaining) % 60
let timeToDisply = String(format:"%02i:%02i", minutesLeft, secondsLeft)
timeLabel.text = timeToDisply
//Updating the progressBar View:
let cal = calculateManager.updateProgressView(seconds: secondsPassed, time: totalTime)
circleProgressView.setProgress( cal , animated: true)
if timeRemaining <= 0 {
//what happen once we finish the 25mins:
timer.invalidate()
//Updating the tasks:
if completedTasks < 10 {
completedTasks += 1
}
tasksLabel.text = "Tasks: \(completedTasks)/10"
//TODO: Play the sound that the user chose:
//Setting up the timer to 5mins break after an interval is done:
timeLabel.text = T.breakTime // Setting up the TimeLabel to be 5:00 of the break
timeRemaining = T.breakInMins // Setting up the totalTime to 300seconds which is 5 mins
playSymbol.setBackgroundImage(UIImage(named: T.P.playPic), for: .normal) // Setting up the Icon to the play button.
}
}
//MARK: - Reset Function:
@IBAction func resetTapped(_ sender: UIButton) {
let alert = UIAlertController(title: "Are you sure you want to skip this task?", message: .none, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Skip", style: .destructive, handler: { action in
//Once the user wants to reset the task - known as the Reset Button.
self.timer.invalidate()
self.timeRemaining = 1500
self.timeLabel.text = "25:00"
self.textField.text = "" //setting the textfield to be empty
self.timerIsOn = false
self.playSymbol.setBackgroundImage(UIImage(named: T.P.playPic), for: .normal)
self.circleProgressView.setProgress( T.resetProgress , animated: false)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true)
}
//MARK: - Settings Section:
@IBAction func settingsPreesedButton(_ sender: UIButton) {
}
}
//MARK: - UITextField Delegate Methods:
extension PomodoroViewController: UITextFieldDelegate
{
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
extension PomodoroViewController: CalculateManagerDelegate {
func updateTotalTime(time: Int) {
timeRemaining = time
}
}
my second ViewController:
import Foundation
import UIKit
import AVFoundation
import PickerViewCell
//MARK: - Settings View Controller:
class SettingsViewController: UITableViewController, PickerTableCellDelegate, PickerTableCellDataSource {
@IBOutlet weak var workInterval: UILabel!
@IBOutlet weak var shortBreak: UILabel!
@IBOutlet weak var longBreakAfter: UILabel!
@IBOutlet weak var dailyIntervals: UILabel!
let defaults = UserDefaults.standard
var calculateManager = CalculateManager()
override func viewDidLoad() {
checkForSavedWorkTime()
}
var timesDictionary = [0: "30 Minutes",
1: "25 Minutes",
2: "20 Minutes",
3: "15 Minutes",
4: "10 Minutes",
5: "5 Minutes"
]
var intervalsDictionary = [ 0: "1 Intervals",
1: "2 Intervals",
2: "3 Intervals",
3: "4 Intervals",
4: "5 Intervals",
5: "6 Intervals",
6: "7 Intervals",
7: "8 Intervals",
8: "9 Intervals",
9: "10 Intervals"
]
var totalWorkTime = 0
//MARK: Picker TableCell Delegate Methods:
//This func chooses the title of every row in the UIPickerView selection:
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int, forCell cell: PickerTableViewCell) -> String? {
let identifier = cell.reuseIdentifier
switch identifier {
case "timeCell":
return timesDictionary[row]
case "shortBreakCell":
return timesDictionary[row]
case "longBreakAfterCell":
return timesDictionary[row]
case "intervalsCell":
return intervalsDictionary[row]
default:
print("There was a problem with titleforrow")
}
return nil
}
//This func takes control of what will happen once the user choose an optaion in the UIPickerView Selection:
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int, forCell cell: PickerTableViewCell) {
let identifier = cell.reuseIdentifier
switch identifier {
case "timeCell":
workInterval.text = timesDictionary[row]
let myString = workInterval.text!
if let totalTime = calculateManager.calculateTotalTime(convertString: myString) {
totalWorkTime = totalTime
}
saveTime(labelText: myString)
case "shortBreakCell":
shortBreak.text = timesDictionary[row]
case "longBreakAfterCell":
longBreakAfter.text = timesDictionary[row]
default:
print("There was a problem with Switch")
}
self.view.endEditing(true)
}
func saveTime(labelText: String) {
defaults.set(labelText, forKey: "workInterval")
}
func checkForSavedWorkTime() {
if let time = defaults.string(forKey: "workInterval") {
workInterval.text = time
}
}
func onPickerOpen(_ cell: PickerTableViewCell) {
}
func onPickerClose(_ cell: PickerTableViewCell) {
}
//MARK: Picker TableCell DataSource:
func numberOfComponents(in pickerView: UIPickerView, forCell cell: PickerTableViewCell) -> Int {
return 1
}
//the amount of rows in component(UIPicker):
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int, forCell cell: PickerTableViewCell) -> Int {
if cell.reuseIdentifier == "timeCell"{
return timesDictionary.count
}
return intervalsDictionary.count
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: indexPath) as? DatePickerTableViewCell {
// cell.delegate = self
if !cell.isFirstResponder {
_ = cell.becomeFirstResponder()
}
} else if let cell = tableView.cellForRow(at: indexPath) as? PickerTableViewCell {
cell.delegate = self
cell.dataSource = self
if !cell.isFirstResponder {
_ = cell.becomeFirstResponder()
}
}
}
}
//MARK: - Completed View Controller:
class CompletetedSoundViewController: UITableViewController {
/// Class Variables
private var soundsArray = [Track]()
override func viewDidLoad() {
// tableView.delegate = self
// tableView.dataSource = self
}
///TableView Data Soruce Methods:
// Return the number of rows for the table.
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return soundsArray.count
}
// Provide a cell object for each row.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Fetch a cell of the appropriate type.
tableView.deselectRow(at: indexPath, animated: true)
let cell = tableView.dequeueReusableCell(withIdentifier: "trackCell", for: indexPath)
// Configure the cell’s contents.
cell.textLabel!.text = soundsArray[indexPath.row].trackName
return cell
}
///TableView Delegate Methods:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
}
//MARK: - Break Sound Controller:
class BreakSound: UITableViewController {
override func viewDidLoad() {
//
}
}
my Struct:
import Foundation
import UIKit
protocol CalculateManagerDelegate {
func updateTotalTime(time: Int)
}
struct CalculateManager {
var totalAmountOfTime = 0
var delegate: CalculateManagerDelegate?
//TODO: Calculate the Progress-View:
func updateProgressView(seconds: Int, time: Int ) -> Double {
return Double(seconds) / Double(time)
}
mutating func calculateTotalTime(convertString: String) -> Int? {
let newString = convertString.dropLast(8)
let subToString = String(newString)
if let turnToInt = Int(subToString)
{
totalAmountOfTime = turnToInt * 60
delegate?.updateTotalTime(time: totalAmountOfTime)
return totalAmountOfTime
}
return nil
}
}