title: REST API, Swift, Automatic Update
body: <p>I'm currently struggling to find an easy-to-use programming approach/design pattern, which solves the following problem:</p>
  
  <p>I've got an REST API where the iOS app can request the required data. The data is needed in different ViewControllers. But the problem is, that the data should "always" be up to date. So I need to set up a timer which triggers a request every 5-20 seconds, or sth like that. Everytime the data changes, the view needs to be updated (at the current viewcontroller, which is displayed).
  I tried some stuff with delegation and MVC Pattern, but it's kind a messy. How is it done the right way?</p>
  
  <p>In my current implementation I only can update the whole UICollectionView, not some specific cells, because I don't know how the data changed. My controller keeps track of the data from the api and updates only if the hash has changed (if data changed on the server). My models always holds the last fetched data.
  It's not the perfect solution, in my opinion..</p>
  
  <p>I also thought about models, that keep themselves up to date, to abstract or virtualise my Rest-API. In this case, my controller doesn't even know, that it isn't directly accessible data.</p>
  
  <p>Maybe someone can help me out with some kind of programming model, designpattern or anything else. I'm happy about anything!</p>
  
  <hr>
  
  <p>UPDATE: current implementation</p>
  
  <p>The Controller, which handles all the data</p>
  
  <pre><code>import Foundation
  import SwiftyJSON
  import SwiftyTimer
  
  class OverviewController {
  
    static let sharedInstance = OverviewController()
  
    let interval = 5.seconds
    var delegate : OverviewControllerUpdateable?
    var model : OverviewModel?
    var timer : NSTimer!
  
    func startFetching() -&gt; Void {
      self.fetchData()
  
      timer = NSTimer.new(every: interval) {
        self.fetchData()
      }
  
      timer.start(modes: NSRunLoopCommonModes)
    }
  
    func stopFetching() -&gt; Void {
      timer.invalidate()
    }
  
    func getConnections() -&gt; [Connection]? {
      return model?.getConnections()
    }
  
    func getConnectionsSlave() -&gt; [Connection]? {
      return model?.getConnectionsSlave()
    }
  
    func getUser() -&gt; User? {
      return model?.getUser()
    }
  
    func countConnections() -&gt; Int {
      if let count = model?.getConnections().count {
        return count
      }
      return 0
    }
  
    func countConnectionsSlave() -&gt; Int {
      if let count = model?.getConnectionsSlave().count {
        return count
      }
      return 0
    }
  
    func fetchData() {
      ApiCaller.doCall(OverviewRoute(), completionHandler: { (data, hash) in
  
        if let actModel = self.model {
          if (actModel.getHash() == hash) {
            //no update required
            return
          }
        }
  
        var connections : [Connection] = []
        var connectionsSlave : [Connection] = []
  
        for (_,connection):(String, JSON) in data["connections"] {
          let connectionObj = Connection(json: connection)
          if (connectionObj.isMaster == true) {
            connections.append(connectionObj)
          } else {
            connectionsSlave.append(connectionObj)
          }
        }
  
        let user = User(json: data["user"])
  
        //model needs update
        let model = OverviewModel()
        model.setUser(user)
        model.setConnections(connections)
        model.setConnectionsSlave(connectionsSlave)
        model.setHash(hash)
  
        self.model = model
  
        //prevent unexpectedly found nil exception
        if (self.delegate != nil) {
          self.delegate!.reloadView()
        }
  
        }, errorHandler: { (errors) in
        }) { (progress) in
      }
    }
  }
  
  protocol OverviewControllerUpdateable {
    func reloadView()
  }
  </code></pre>
  
  <p>The model, which holds the data:</p>
  
  <pre><code>class OverviewModel {
  
    var user : User!
    var connections : [Connection]!
    var connectionsSlave : [Connection]!
    var connectionRequests : [ConnectionRequest]!
    var hash : String!
  
  ...
  }
  </code></pre>
  
  <p>And in the ViewController, I use it like this:</p>
  
  <pre><code>class OverviewVC: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, OverviewControllerUpdateable {
  
      let controller = OverviewController.sharedInstance
  
      override func viewDidLoad() {
          super.viewDidLoad()
          self.controller.delegate = self
          self.controller.startFetching()
      }
  
      //INSIDE THE UICOLLECTIONVIEW DELEGATE METHODS
      ...
      if let user : User = controller.getUser() {
        cell.intervalTime = interval
        cell.nameLabel.text = "Ihr Profil"
      }
      ...
  
      func reloadView() {
          self.userCollectionView.reloadData()
      }
  }
  </code></pre>