2017-07-31 12 views
0

私は次のような場合があります。ルートコントローラはUITabViewControllerです。 ProfileViewControllerがあります。その中に、ユーザーが友だちになり始めた(そして画面の機能が変わる)というオブザーバーを作ります。 ProfileViewControllerは5つのうち4つのタブで開くことができ、現在のユーザーは同じユーザーで4つの場所で画面を開くことができます。以前のバージョンでは、ProfileViewControllerが1か所で開かれたときに、私はdeinitでオブザーバを削除し、ちょうどref.removeAllObservers()で削除しました。ユーザーのケースでは、viewDidDisappearのハンドルと削除オブザーバを使い始めました。私はそれが改善できるかどうか、そしてこの状況で私が正しくそれをやっているかどうかを調べるコードを実証したいと思います。SwiftのFirebaseのハンドルを使ってオブザーバを外す

私はこれはそれぞれのViewControllerへの参照を維持するの実装に関するFIRFriendsDatabaseManager

fileprivate var observeSpecificUserFriendshipStartDict = [AnyHashable : UInt]() 


func observeSpecificUserFriendshipStart(observer: Any, isObserve: Bool, userID: String, success: ((_ friendModel: FriendModel) -> Void)?, fail: ((_ error: Error) -> Void)?) { 
     let realmManager = RealmManager() 
     guard let currentUserID = realmManager.getCurrentUser()?.id else { return } 
     DispatchQueue.global(qos: .background).async { 
      let specificUserFriendRef = Database.database().reference().child(MainGateways.friends.description).child(currentUserID).child(SubGateways.userFriends.description).queryOrdered(byChild: "friendID").queryEqual(toValue: userID) 

      if !isObserve { 
       guard let observerHashable = observer as? AnyHashable else { return } 
       if let handle = self.observeSpecificUserFriendshipStartDict[observerHashable] { 
        self.observeSpecificUserFriendshipStartDict[observerHashable] = nil 
        specificUserFriendRef.removeObserver(withHandle: handle) 
        debugPrint("removed handle", handle) 
       } 
       return 
      } 

      var handle: UInt = 0 

      handle = specificUserFriendRef.observe(.childAdded, with: { (snapshot) in 
       if snapshot.value is NSNull { 
        return 
       } 
       guard let dict = snapshot.value as? [String : Any] else { return } 
       guard let friendModel = Mapper<FriendModel>().map(JSON: dict) else { return } 

       if friendModel.friendID == userID { 
        success?(friendModel) 
       } 
      }, withCancel: { (error) in 
       fail?(error) 
      }) 

      guard let observerHashable = observer as? AnyHashable else { return } 
      self.observeSpecificUserFriendshipStartDict[observerHashable] = handle 
     } 
    } 
+0

あなたのコードは正常に機能しており、あなたの質問は「これを行うためのより良い方法は私が行ったことよりも優れていますか?これが正しい場合。ここに私のフィードバックがあります。あなたの論理は、あなたが達成したいと述べたことを考慮して、私にとっては妥当と思われます。また、あなたのコードに対するフィードバックの一般的なポイントとして、 'observeSpecificUserFriendshipStart'をリファクタリングしてもっと読みやすくすることができます。 – Doug

+0

@Dougはい、あなたは正しく質問を理解しました。私はそれが好きではありません。辞書にコントローラへのリンクが格納されているので、おそらくオプションが良いかもしれないと思います) – Alexander

+0

@Dougこの変形例では、たとえば、オブザーバーを削除するケースがあれば、マネージャーは辞書内のコントローラーへのリンクを取得します。 – Alexander

答えて

1

であり、私はの延長にロジックを移動することを検討してしまう

fileprivate func firObserve(_ isObserve: Bool) { 
     guard let _user = user else { return } 
     FIRFriendsDatabaseManager.shared.observeSpecificUserFriendshipStart(observer: self, isObserve: isObserve, userID: _user.id, success: { [weak self] (friendModel) in 
     }) { (error) in 

     } 
    } 

viewWillAppear

でこの関数を呼び出しますviewController自体です。

あなたが以前と同じようにref.removeAllObservers()を呼び出すことを避けたい場合は、viewControllerごとにこれらのリスナーの1つだけがあると仮定します。私はリスナーrefをビューコントローラ上の変数にしたいと思います。

このように、すべてがviewControllerにのみ含まれています。また、他のタイプのviewControllerが同様のタイプのリスナーの管理を行っている場合は、プロトコルを作成するための候補になる可能性があります。

関連する問題