1

I've implemented a counter in my app, and it works. Then, when I change of ViewController (When i run my app), my counter reset to 0 automatically. I want my counter to continue while i'm using the app.

Thank's for your Help :)

import UIKit

class ViewController: UIViewController
{
    /// Label
    private var customLabel : UILabel?

    /// MAximum Count to which label will be Updated
    private var maxCount : Int?
    /// Count which is currently displayed in Label
    private var currentCount : Int?
    /// Timer To animate label text
    private var updateTimer : Timer?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        customLabel = UILabel()
        customLabel?.textColor = .white
        customLabel?.font = UIFont(name: "HelveticaNeue-Bold", size: 25)
        customLabel?.textAlignment = .center


        /// Add label to View
        addConstraints()

        /// Start Timer
        DispatchQueue.main.async {
            self.maxCount = 600
            self.currentCount = 1
            self.updateTimer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(ViewController.updateLabel), userInfo: nil, repeats: true)
        }
    }

    @objc func updateLabel() {
        self.customLabel?.text = String(currentCount!)
        currentCount! += 1
        if currentCount! > maxCount! {
            /// Release All Values
            self.updateTimer?.invalidate()
            self.updateTimer = nil
            self.maxCount = nil
            self.currentCount = nil
        }
    }

    func addConstraints(){
        /// Add Required Constraints
        self.view.addSubview(customLabel!)
        customLabel?.translatesAutoresizingMaskIntoConstraints = false
        customLabel?.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 195).isActive = true
        customLabel?.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -50).isActive = true
        customLabel?.heightAnchor.constraint(equalToConstant: 50).isActive = true
        customLabel?.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 310).isActive = true
    }
}
C.OG
  • 6,236
  • 3
  • 20
  • 38
  • You can declare a global variable or you can use a struct to store the variable. Check my answer. – Keshu R. Dec 23 '19 at 12:38
  • Perhaps each time you create a new view controller (be careful - there may be a memory leak) and the counter starts over. I have tested your code with two ViewControllers (switched between them) - the counter continued to work. Therefore, the problem is the implementation of the life cycle of the view controller, and not the implementation of the counter – Vadim Nikolaev Dec 23 '19 at 12:47
  • Thank's @VadimNikolaev . You're right, it's a ViewController issue. I've just seen that with some of my viewController the counter continue, but with some it reset to 0. How can i fix this problem ? – Alexis Decloedt Dec 23 '19 at 12:51
  • @AlexisDecloedt to understand how to fix it - you need to look at the full implementation of creating issued view controller (the place where the view controller is created). FYI: using force unwrapping is a high risk of application crash, try a different option for setting variables (for example, e.g. predefined variables like `private let maxCount : Int = 600` and `private var currentCount : Int = 1` – Vadim Nikolaev Dec 23 '19 at 13:01
  • @VadimNikolaev where can i find the exact place where the view controller was created ? (sorry i'm a beginner). I can't see any difference between my different ViewController :/ – Alexis Decloedt Dec 23 '19 at 13:07
  • @AlexisDecloedt I guess you should debug this place (for finding the exact place). Unfortunately, not seeing the full implementation of the application, I can not predict – Vadim Nikolaev Dec 23 '19 at 13:25

4 Answers4

1

Declare these two var and let:

var defaults  = UserDefaults.standard
let countKey = "CountKey"

Add this line of code whenever you update your counter:

defaults.set(currentCount, forKey: countKey)

To get back your value instead, use:

defaults.integer(forKey: countKey)
0

What actually happening is that whenever you come back to your ViewController You are creating a new counter What you need to do is Declare your counter Outside viewDidLoad() but make sure that your ViewController is the root ViewController of your app that never gets deinitialised otherwise your app will crash.

0

My recommendation would be implementing the Timer thing in your root controller which will not die until your app gets terminated like your Navigation Controller/Tab Controller, and keep updating the label whenever the 'ViewController' appears.

Thats how it will work even when the Controller is dead.

Zeeshan Ahmed
  • 834
  • 8
  • 13
0

Your counter is actually part of your view controller which lives in memory, and when you restart your app (from Xcode I assume). It is removing your app from device memory, that's why you are losing your timer count.

Best thing you can do is saving you timer count to User Defaults (which saves it to disk), which means when you reopen your app you can get it from User Defaults and continue changing your current count

Canberk Ersoy
  • 428
  • 1
  • 5
  • 13