2016-05-30 13 views
0

tableViewを再ロードする際に問題があります。私のfirebaseService.getAllPosts()メソッドが実行されると、データベースに2つの投稿が表示されます。私はdidSet印刷が実行されるとき、それが私に正しいカウントを与えるので、これを言うことができます。しかし、メソッドが実行される前にtableviewが設定されていることがわかっているので、データソースのカウントを更新するためにtableviewをリロードする必要があります。そこに問題がある。私はposts変数を私のクラスの外に入れて、すべてのクラスからアクセスできるようにしました。 (これは良い練習ではない場合、私に教えてください)テーブルの再読み込みに問題があります

私はtableView.reloadData()を実行することができますので、私のtableViewデータソースの更新は、私にpostsの正しいことを教えてくれますか?私はFeedController().tableView.reloadData()をdidSetに入れてみましたが、私はviewDidLoad()に入れてみましたが、どちらもうまくいきませんでした。私はまた、_postsという変数を追加し、postsに等しい、それを設定し、didSet内部tableView.reloadData()とそれにdidSetを追加しようとしたが、それはどちらか動作しません。

class FeedController: UIViewController, UITableViewDelegate, UITableViewDataSource { 

    let tableView = UITableView(frame: UIScreen.mainScreen().bounds, style: UITableViewStyle.Plain) 
    let cellId = "PhotoCell" 
    let textCellId = "TextCell" 
    let firebaseService = FirebaseService.sharedInstance 
    static let sharedFeedInstance = FeedController() 
    var posts = [Post]() { 
    didSet { 
     tableView.reloadData() 
     print(posts.count) 
     } 
    } 



    override func viewDidLoad() { 
     super.viewDidLoad() 

     firebaseService.getAllPosts() 

     tableView.dataSource = self 
     tableView.delegate = self 
     self.view.addSubview(tableView) 

    } 

    // MARK: - Table view data source 

    func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
     // #warning Incomplete implementation, return the number of sections 
     print("sections: \(posts.count)") 
     return posts.count 
    } 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     // #warning Incomplete implementation, return the number of rows 
     return 1 
    } 

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

     let post:Post? = posts[indexPath.section] 


     if let _ = post?.imageContentName { 
      let photoFeedCell = tableView.dequeueReusableCellWithIdentifier(self.cellId, forIndexPath: indexPath) as? FeedTVCellWithPhoto 
      photoFeedCell?.post = post 
      return photoFeedCell! 
     } 

     let textFeedCell = tableView.dequeueReusableCellWithIdentifier(self.textCellId, forIndexPath: indexPath) as? FeedTVCellText 
     textFeedCell?.post = post 
     return textFeedCell! 
    } 
} 

アップデート1:FirebaseServiceクラスからgetAllPosts方法

func getAllPosts() { 
     let postRef = ref.child("posts") 
     postRef.observeSingleEventOfType(.Value, withBlock: { snapshot in 
//   print(snapshot.value) 
      if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] { 
       for snap in snapshots { 
        if let postDictionary = snap.value as? Dictionary<String, AnyObject> { 
         let key = snap.key 
         let post = Post(key: key, dictionary: postDictionary) 
         FeedController.sharedFeedInstance.posts.insert(post, atIndex: 0) 
        } 
       } 
      } 

     }) 
    } 
+0

問題は、画面上にあるビューコントローラのコンテキストで 'reloadData'を実行する必要があることです。 'FeedController()。tableView.reloadData()'は、 'FeedController'の新しいインスタンスを作成しますが、これは役に立ちません。あなたが望むものを得ることができる1つの方法は、 'didSet'からNSNotificationを投稿し、関心のあるビューコントローラにそれをサブスクライブさせることです。そして、はい、グローバル変数は悪い考えです。シングルトンクラスを作成するか、1つのインスタンスを作成して各ビューコントローラに渡します。 – Paulw11

+0

'reloadData'を呼び出すには、' getAllPosts'がいつ終了するかを知る必要があります。 'getAllPosts'はどのように見えますか? – Cristik

答えて

0

本質的には、FeedControllerのメソッドとプロパティに間違った方法で対処しています。コードにFeedController()を使用するたびにselfを使用する必要があります。

次の二つの段落では、クラス、インスタンスメソッドとプロパティについて復習しています。それはあなたのレーダーにすでに何かだ場合は、それらを無視して自由に感じる:

  • メソッドやプロパティはインスタンスに属している場合(つまり、それはインスタンスからインスタンスに変更される場合があります)あなたはself.propertyまたはself.method()でそれを呼び出し、あいまいさを生じさせない限り、しばしばself.を削除することができます。

  • メソッドやプロパティは、クラス全体に属し(したがって、それはstatic letstatic varまたはstatic funcとして宣言されている)なら、あなたはNameOfTheClass.propertyまたはNameOfTheClass.method()でそれを呼び出します。あなたの場合は、FeedController.propertyまたはFeedController.method()とします。つまり、末尾のかっこのないです。どのような場合でも、クラスのメソッドとプロパティは控えめに使用する必要があり、この状況ではおそらく適切ではありません。

これを解決したら、データをリロードする方法があります。 postsFeedController(配列変数をインスタンス変数にする)に移動し、didSet()poststableView.reloadData()を追加すると、他の関連性のないコードの匂いにもかかわらず、修正する必要があります。それらはデータをリロードする能力に影響を与えるべきではありません。

+0

ありがとうございました。それは本当に役立ちます。ここでrubがあります。私のfirebaseServiceクラスは、データベースからアイテムを追加できるように、投稿にアクセスする必要があります(更新されたコードを参照)。 FirebaseServiceクラスの投稿にアクセスする最も良い方法は何ですか? –

+0

クラスの新しい静的定数を作成し、それを参照しました。私はそれが正しいと仮定していますか?それで、すべてがコンパイルされますが、セクションを正しく更新することができません。投稿のdidSetは2のカウントを返していますが、セクションカウントは更新されているようには見えません。 –

+0

いいえこれで 'FeedController'がシングルトンになりました。これはPG13を賢明に保つためです。シングルトンは控えめに使用する必要のあるパターンで、モデルレイヤーの特定のコンポーネントに適用する時間の99%です。実質的にVC層には決してない。 – catalandres

0

だから、バットオフ:

  • "FeedController()tableView.reloadData()" は別のインスタンス化されますFeedController。それはうまくいかないでしょう。リロードコールを置く場所は、要件によって異なります。あなたはこののUIViewControllerに前後に移動して、データを他のUIViewControllersに変更されている場合に発生するseguesの多くを持っている場合たとえば、あなたはviewWillAppear()または他のライフサイクルメソッドのオーバーライドでリロードすることができます。 UIWindowにロードされているUIViewControllerのインスタンスのtableView上で呼び出す必要があります。
  • あなたはプログラムではなく ストーリーボード経由よりもこのようなものをたくさんやっている理由は、任意の理由は?いずれにしても問題ありませんが、ストーリーボード はすばらしく分かれています。たとえば、ストーリーボードを使用してUITableViewControllerを使用した場合、醜い定型文のように見えるコードでデリゲートとデータソースを設定することはできません。プロトコルを満たしている限り、UITableViewControllerを使用せずにこれらを設定することもできます。ストーリーボードで処理できるものはでなければなりません。
  • あなたのクラスがなぜただのUITableViewControllerを拡張していない、のUIViewControllerを拡張し、これら2つのプロトコルを実装していますか?あなたは手動でそこにUITableViewを入れて、そのUIViewController上にUITableView以外の何かを表示する必要がない限り、私はあなたがやっていることを行うことができる理由はありません。
  • 注意する何か他のものは、あなたがPhotoFeedCellとTextFeedCellをやっている方法は、一種の奇妙であると混合された信号を与えることです。あなたは再利用可能なセルをデキューしています。オプションでそれをキャストし、後にオプションの連鎖を使用しています。どちらも受け入れようとしていることを意味しますが、直ちにアンラップします。
+0

これは答えではありません –

+0

別のFeedControllerのインスタンス化がうまくいかず、どこに置くのが答えではないとあなたに言った部分ですか? "tableView.reloadData()を実行すると、tableViewデータソースが更新され、正しいポストが得られますか?" "reload呼び出しを配置する場所は、必要に応じて異なります。たとえば、このUIViewControllerを前後に移動し、他のUIViewControllerでデータが変更されている箇所が多い場合は、 viewWillAppear()または他のライフサイクルメソッドの " – Jay

+0

私は既に何かのように私のポストでそれを試したと働いていないと言った。あなたがどこにそれを置くべきかを言う限り、あなたはこれに関係しない例があります。私はセグーやIBを使っていません。 –

関連する問題