【发布时间】: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