0

I want to make a timer that start on app load and when it finishes to alert a text and restart the app when alert is closed(when click the ok button of the alert). Have tried with a class timer but I can't send alert and reload the app. I need it to be working in the whole app, and when move to other view not restart it countdown. Is there any easy way without using CocoaPods.

import Foundation

class GlobalTokenTimer {
    static let sharedTimer: GlobalTokenTimer = {
        let timer = GlobalTokenTimer()
        return timer
    }()

    var internalTimer: Timer?
    var jobs = [() -> Void]()

    func startTimer(withInterval interval: Double, andJob job: @escaping () -> Void) {
        if internalTimer != nil {
            internalTimer?.invalidate()
        }
        jobs.append(job)
        internalTimer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(doJob), userInfo: nil, repeats: true)
    }

    func stopTimer() {
        guard internalTimer != nil else {
            print("No timer active, start the timer before you stop it.")
            return
        }
        jobs = [()->()]()
        internalTimer?.invalidate()
    }

    @objc func doJob() {
        guard jobs.count > 0 else{return}
    }
}
theduck
  • 2,589
  • 13
  • 17
  • 23
Martin
  • 13
  • 2
  • 1
    Possible adding duplicate questions. Similar question was added few hours ago [Question](https://stackoverflow.com/q/57767575/4056108) – chirag90 Sep 03 '19 at 10:48

1 Answers1

1

Your timer is static and will work while app is alive. Implement some function that will show alert on topViewController of your application.

extension UIApplication {
    // function that lets you get topViewController of the app
    func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }

        if let tabController = controller as? UITabBarController {
            if let selected = tabController.selectedViewController {
                return topViewController(controller: selected)
            }
        }

        if let presented = controller?.presentedViewController {
            return topViewController(controller: presented)
        }

        return controller
    }

}

Inside your app delegate start your timer and show alert. In iOS you can't restart you app, but can set newly created MyStartViewController which is your home page for example and restart logic of your app.

UPD:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func startTimer() {
        GlobalTokenTimer.sharedTimer.startTimer(withInterval: 10) {
            let alertVC = UIAlertController(title: "Restart your app!", message: "Select ok!", preferredStyle: .alert)
            alertVC.addAction(UIAlertAction(title: "Restart", style: .default) { [weak self] _ in
                self?.window?.rootViewController = MyStartViewController()
                startTimer()
            })

            application.topViewController()?.present(alertVC, animated: true)
        }
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        startTimer()
    }
}

Set your timer repeat: false and it would stop after finishing once.

internalTimer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(doJob), userInfo: nil, repeats: false)

UPD: You do nothing in your doJob function, change it to this.

@objc func doJob() {
    guard jobs.count > 0 else { return }

    jobs.forEach { $0() }
}
えるまる
  • 2,409
  • 3
  • 24
  • 44