【问题标题】:REST API, Swift, Automatic UpdateREST API、Swift、自动更新
【发布时间】:2017-03-08 03:47:45
【问题描述】:

我目前正在努力寻找一种易于使用的编程方法/设计模式,它可以解决以下问题:

我有一个 REST API,iOS 应用可以在其中请求所需的数据。不同的 ViewController 需要数据。但问题是,数据应该“始终”是最新的。所以我需要设置一个定时器,它每 5-20 秒触发一次请求,或者类似的东西。每次数据更改时,都需要更新视图(在当前视图控制器上,显示出来)。 我用委托和 MVC 模式尝试了一些东西,但它有点乱。如何以正确的方式完成?

在我当前的实现中,我只能更新整个 UICollectionView,而不是某些特定的单元格,因为我不知道数据是如何变化的。我的控制器跟踪来自 api 的数据,并且仅在哈希发生更改时才更新(如果服务器上的数据发生更改)。我的模型总是保存最后获取的数据。 在我看来,这不是完美的解决方案..

我还考虑了模型,它们可以使自己保持最新状态,以抽象或虚拟化我的 Rest-API。在这种情况下,我的控制器甚至不知道它不是可直接访问的数据。

也许有人可以通过某种编程模型、设计模式或其他任何东西帮助我。我对任何事情都感到高兴!


更新:当前实现

控制器,处理所有数据

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() -> Void {
    self.fetchData()

    timer = NSTimer.new(every: interval) {
      self.fetchData()
    }

    timer.start(modes: NSRunLoopCommonModes)
  }

  func stopFetching() -> Void {
    timer.invalidate()
  }

  func getConnections() -> [Connection]? {
    return model?.getConnections()
  }

  func getConnectionsSlave() -> [Connection]? {
    return model?.getConnectionsSlave()
  }

  func getUser() -> User? {
    return model?.getUser()
  }

  func countConnections() -> Int {
    if let count = model?.getConnections().count {
      return count
    }
    return 0
  }

  func countConnectionsSlave() -> 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()
}

保存数据的模型:

class OverviewModel {

  var user : User!
  var connections : [Connection]!
  var connectionsSlave : [Connection]!
  var connectionRequests : [ConnectionRequest]!
  var hash : String!

...
}

在 ViewController 中,我是这样使用的:

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()
    }
}

【问题讨论】:

  • 你能澄清一下目前的问题吗?也许显示一些代码?
  • 更新了帖子!
  • 推送通知比轮询更好,但如果你不能这样做,那么带有计时器的单例是另一种方法。查看 IGListKit 以更新集合视图 - github.com/Instagram/IGListKit
  • 我明白你的意思,你是完全正确的。但就我而言,推送是没有选择的。将我的数据从我的 api 直接保存到 coredata 中并且我的视图只从 coredata 中读取数据是否有意义?

标签: ios swift rest model-view-controller


【解决方案1】:

您可以使用Singleton 对象定期获取您的数据,然后在数据更新时发布通知(使用NSNotificationCenter)。每个依赖于数据的视图控制器都会监听这些通知,然后根据更新的数据重新加载 UI。

【讨论】:

  • 我认为 NSNotificationCenter 是为我做的。委派只适用于一个 VC,使用观察者模式我可以使用多个 VC。我现在实际上实现了它,它工作正常。一遍又一遍地设置代表团没有混乱。如果还没有获取数据,我还更改了我的控制器并将数据持久保存并加载它。我还实现了 IGListKist 中使用的算法来计算 UICollectionView 的变化。
  • 这是个好消息。观察者模式对这个用例很有意义。将来,您可以考虑在数据获取器上创建自己的侦听器协议,就像使用委托一样,但能够一次注册多个侦听器。这比NSNotificationCenter 干净一点,因为它强制侦听器遵守协议。通知中心使用的目标/动作模式不是很“Swifty”
  • 你完全正确。我将阅读它并重构我的代码。谢谢,伙计!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多