2017-04-21 6 views
0

私はViewControllerクラスの先頭にrequestPostArrayを宣言しました。私は、 "Request Posts"というデータベースからrequestPostArrayを読み込み、requestPostArrayからtableViewを生成しようとしています。しかし、私はそれのサイズを印刷するときに0に表示されます。どんな助けも高く評価されます。クロージャー外の変数へのアクセスSwift3

また、以下のelse文全体は別のクロージャの中にあります。

else { 

      ref.child("Request Posts").observe(.value, with: { (snapshot) in 
       let count = Int(snapshot.childrenCount) 

       // Request Post database is empty 
       if count == 0 { 
        cell.nameLabel.text = "No requests so far." 
        cell.userNameLabel.isHidden = true 
        cell.numberOfRequestsLabel.isHidden = true 
       } 

       // Request Post data is populated 
       else { 

        var requestPostArray: [RequestPost]? = [] 
        self.ref.child("Request Posts").observe(.value, with: { (snapshot) in 
         if let result = snapshot.children.allObjects as? [FIRDataSnapshot] { 

          for child in result { 
           let post = RequestPost(snapshot: child) 
           requestPostArray?.append(post) 
          } 
         } 

         else { 
          print("No Result") 
         } 
        }) 


        print("RequestPostArray size = \(requestPostArray?.count ?? 90)") 

        cell.nameLabel.text = self.requestPostArray?[indexPath.row].name 
        cell.userNameLabel.text = self.requestPostArray?[indexPath.row].name 
        cell.numberOfRequestsLabel.text = self.requestPostArray?[indexPath.row].name 
       } 
      }) 
     } 

答えて

1

これは、observe関数が非同期でコードの残りの部分が同期であるために発生します。また、requestPostArray?からオプションのアンラップを削除すると、非同期タスクは実行に時間がかかるため、コンパイラはその前にsnycタスクを実行します。あなたは、オブジェクトの再利用を得ることができ、あなたが今やっているようにあなたが同じ方法でデータベースのいくつかの時間を起動しないように は基本的にあなたがしなければならないものを、次の

else { 

       ref.child("Request Posts").observe(.value, with: { (snapshot) in 
        let count = Int(snapshot.childrenCount) 

        // Request Post database is empty 
        if count == 0 { 
         cell.nameLabel.text = "No requests so far." 
         cell.userNameLabel.isHidden = true 
         cell.numberOfRequestsLabel.isHidden = true 
        } 

        // Request Post data is populated 
        else { 

         var requestPostArray: [RequestPost]? = [] 
         self.ref.child("Request Posts").observe(.value, with: { (snapshot) in 
          if let result = snapshot.children.allObjects as? [FIRDataSnapshot] { 

           for child in result { 
            let post = RequestPost(snapshot: child) 
            requestPostArray?.append(post) 
           } 
          } 

          else { 
           print("No Result") 
          } 
print("RequestPostArray size = \(requestPostArray?.count ?? 90)") 

         cell.nameLabel.text = self.requestPostArray?[indexPath.row].name 
         cell.userNameLabel.text = self.requestPostArray?[indexPath.row].name 
         cell.numberOfRequestsLabel.text = self.requestPostArray?[indexPath.row].name 
         }) 



        } 
       }) 
      } 

別のアドバイスは、シングルトンを使用して考えています。

+0

ありがとうAchref!私はSwiftに比較的新しいので、シングルトンが何であるかは分かりません。それが何であるかを簡単に教えてください。それについてもっと知ることができるリンクを教えてください。ありがとう – pranavhgupta

+0

ここをクリックしてくださいhttp://stackoverflow.com/a/43513805/4442592、私は詳細については、この素晴らしいチュートリアルを読むように招待したいと思います:https://www.raywenderlich。 com/86477/introduction-ios-design-patterns-in-swift-part-1 –

+0

私の回答が役に立ちましたか? –

3

observeブロックが非同期です。 requestPostArrayは、requestPostArray?.append(post)行で修正される前に読んでいます。

このコンテキストでは、このcellオブジェクトの値を入力する方法を知るのは難しいですが、「リクエスト投稿」が必要な場合は、取得できるまで待つ必要があります。

+0

ありがとうジョナ!私は "Request Posts"データベースを行います。私は "RequestPost"と呼ばれるカスタムタイプのオブジェクトを作成し、データベースのすべての子をrequestPostArrayという配列のRequestPostArrayの配列に格納して、メンバーがそのテーブルのセルに値を設定するようにしたいとします。 どのように正確に "私はあなたがそれらを得ることができました。"ブロックの実行が終了した後にのみ起動する特定の関数はありますか? – pranavhgupta

+2

テーブルビューのデータソースの 'cellForRowAtIndexPath'内で非同期クエリを作成しようとしているようです。 'cellForRowAtIndexPath'は即座の結果を必要とするため、クエリが実行されるのを待たずに動作しません。代わりに、この問題を解決するために 'FUITableViewDataSource'(https://github.com/firebase/FirebaseUI-iOS/tree/master/FirebaseDatabaseUI)がどのように設計されているかを考慮してください。 – Jonah

関連する問題