2016-10-25 3 views
1

나는 현재 다음과 같은 문제를 해결하기 쉬운 프로그래밍 방법/디자인 패턴을 찾기 위해 사투를 벌인거야 : 내가 REST API를 가지고REST API를, 스위프트, 자동 업데이트

어디 iOS 앱 필요한 데이터를 요청할 수 있습니다. 다른 ViewController에서 데이터가 필요합니다. 그러나 문제는 데이터가 항상 "최신"이어야한다는 것입니다. 그래서 나는 5 ~ 20 초마다 요청을 트리거하는 타이머를 설정해야합니다. 데이터가 변경 될 때마다 뷰를 업데이트해야합니다 (현재 표시된 뷰 컨트롤러에서 표시됨). 위임 및 MVC 패턴으로 일부 작업을 시도했지만 다소 지저분합니다. 어떻게 올바른 방법으로 진행됩니까?

내 현재 구현에서는 일부 특정 셀이 아닌 전체 UICollectionView 만 업데이트 할 수 있습니다. 데이터가 어떻게 변경되었는지 알지 못하기 때문입니다. 내 컨트롤러는 api에서 데이터를 추적하고 해시가 변경된 경우에만 업데이트합니다 (서버에서 데이터가 변경된 경우). 내 모델에는 항상 마지막으로 가져온 데이터가 저장됩니다. 제 의견으로는 완벽한 솔루션이 아닙니다.

내 rest-API를 추상화하거나 가상화하는 데 필요한 최신 모델을 생각합니다. 이 경우 내 컨트롤러는 직접 액세스 할 수없는 데이터라는 것을 알지 못합니다.

어쩌면 누군가가 어떤 종류의 프로그래밍 모델, designpattern 또는 다른 것을 도와 줄 수 있습니다. 나는 무엇이든 행복하다!


UPDATE : 모든 데이터

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

현재이 문제가 정확히 무엇인지 명확히 할 수 있습니까? 어쩌면 코드를 보여줄 수 있을까요? –

+0

이 (가) 게시물을 업데이트했습니다. – Tobias

+0

푸시 알림은 폴링보다 낫지 만 할 수 없다면 타이머가있는 싱글 톤이 또 다른 접근 방법입니다. 콜렉션 뷰 업데이트를 위해 IGListKit을 살펴보십시오. - https://github.com/Instagram/IGListKit – Paulw11

답변

2

Singleton 개체를 사용하여 주기적으로 데이터를 가져온 다음 데이터가 업데이트되면 알림을 게시 할 수 있습니다 (NSNotificationCenter 사용). 데이터에 종속적 인 각 뷰 컨트롤러는 이러한 알림을 수신 한 다음 업데이트 된 데이터를 기반으로 UI를 다시로드합니다.

+0

나는 NSNotificationCenter가 나를 위해 그것을했다고 생각합니다. 위임은 하나의 VC로만 작동하며 Observer-Pattern으로 둘 이상의 VC를 사용할 수 있습니다. 사실 지금은 그것을 구현하고 잘 작동합니다. 대표단을 계속해서 세우는 일에 지장이 없습니다. 필자는 컨트롤러를 변경하고 데이터를 영구 저장하고 아직 데이터를 가져 오지 않은 경우로드합니다. 또한 UICollectionView에 대한 변경을 계산하기 위해 IGListKist에 사용되는 알고리즘을 구현했습니다. – Tobias

+0

좋은 소식이에요. 옵서버 패턴은이 사용 사례에 대해 많은 의미를가집니다. 앞으로는 델리게이트에서와 같이 데이터 가져 오기에서 자신의 Listener 프로토콜을 만드는 것을 고려해 볼 수 있지만 동시에 여러 리스너를 등록 할 수 있어야합니다. 이것은 리스너가 프로토콜을 준수하도록 강제하기 때문에'NSNotificationCenter'보다 조금 깔끔합니다.알림 센터에서 사용하는 목표/행동 패턴은 "Swifty"가 아닙니다. – daltonclaybrook

+0

당신은 완전히 옳습니다. 나는 그것에 대해 읽고 코드를 리팩터링 할 것이다. 고마워, 친구! – Tobias