The question of the structure, how it should look when there is such a task:

There are 5pcs ViewContoller. Some deduce the state of the device that is communicating on a post request, some solve other problems, but for example, if you call the allergy from the method in the timer, it should be shown throughout the application. It is necessary that this query be repeated every 4 seconds and update all information on all controllers that display the results. In certain conditions, of these 5 controllers, the timer must be stopped and also started (for example, LogIn / LogAut, etc.).

What should this virtual classroom look like with a timer and query and how to manage the timer from other classes? and is the approach correct at all?

thanks in advance

    1 answer 1

    The easiest way is to implement a function that will send a request every four seconds to AppDelegate (or in a separate class). And when you receive a response from the server, send a notification for UIViewContollers. When displaying the screen (viewDidAppear), the controllers subscribe to this notification, and when they close it (viewDidDesappear) they unsubscribe from the notification. To disable the timer, you can also send a notification (already to your class) or simply set a variable, for example, allowUpdateTimer to false directly from UIViewContoller, and check its state (in your class) before accessing the server.

    If the data is not actually updated every 4 seconds, for example, every few minutes, it makes sense to use the notification via Firebase Cloud Messaging or open and hold the WebSocket. The app will spend less battery.


    UPDATE:

    I made a simple example:

    In AppDelegate, we create a timer, make it every 4 seconds call the function of receiving time from the server. The server response sends a notification named update_new_date.

    AppDelegate.swift file

    var timer: Timer? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { timer = Timer.scheduledTimer(timeInterval: 4, target:self, selector: #selector(AppDelegate.update_data), userInfo: nil, repeats: true) return true } func update_data() { Alamofire.request("https://time.is/Moscow").responseJSON { response in if let contentType = response.response?.allHeaderFields["Expires"] as? String { print("Date: \(contentType)") let dataDict:[String: String] = ["date": contentType] NotificationCenter.default.post(name: Notification.Name("update_new_date"), object: nil, userInfo: dataDict) } } } 

    We subscribe to this notification when displaying UIViewControllers:

    UIViewController files:

     override func viewDidAppear(_ animated: Bool) { NotificationCenter.default.addObserver(self, selector: #selector(update_new_date(notification:)), name: Notification.Name("update_new_date"), object: nil) } 

    The incoming notification calls the function of updating the data on the screen:

     func update_new_date(notification: Notification){ if let userInfo = notification.userInfo as? [String: Any] { if let date = userInfo["date"] as? String { time_label.text = date appDelegate.animate_update(view: time_label) } } } 

    When the screen is no longer displayed, we unsubscribe from the notifications:

     override func viewDidDisappear(_ animated: Bool) { NotificationCenter.default.removeObserver(self) } 

    You can stop the timer from anywhere by contacting AppDelegate:

     let appDelegate = UIApplication.shared.delegate as! AppDelegate appDelegate.timer?.invalidate() 

    And run further:

     appDelegate.timer?.fire() 

    Example of automatically updated data

    Full version of the example: Github

    • Thanks for the answer, I waited a long time for someone) So, I understood everything as follows: 1. Create a class with a timer function and query. 2. Install it from appDelegate using .post (...), I accept and start there 3. If I answer successfully, I do .post (...) 4. In the controller, in which I am in viewDidAppear, the receiver .addObserver (.. .) calling certain methods 5. when leaving this controller, I have to unsubscribe from reception in viewDidDisappear or in deinit, .remove (self). - pbogdanv
    • I don’t understand exactly which methods are needed, since there is a post NSnotification.name, but is there any one I need with prescription of my own .postNotificationName (...) name, or is it not important? And is it all true that I listed in the first comment? (I didn't get the characters) Thanks - pbogdanv
    • I added an example in response. Write if it is not clear. - Ivan Kramarchuk
    • A wonderful detailed answer, there is only a question, how to correctly address the timer, if I implemented it in a separate class (Utilits), and not in the Epdelegate? Or just create in each controller a new instance of the let update_data = Utilits() class? Just then it is not the management of the same timer, but each time a new one - pbogdanv
    • Use Singleton to access a single instance of Utilits. - Ivan Kramarchuk