2017-04-05 4 views
0

配列postCaptionsを設定しようとしています。 テーブルビューのnumberOfRowsInSectionにこの配列を返す必要がありますが、毎回空の配列が返されます。パースを使用してPFQueryの外側に空の配列を返す配列

var postCaptions = [String]() 

    query2.whereKey("userid", equalTo: PFUser.current()?.objectId!)       
    query2.findObjectsInBackground(block: { (objects, error) in 
     if let userPosted = objects {  
      for object in userPosted {   
       if let userPost = object as? PFObject {   
        self.postImageFiles.append(userPost["userPostImage"] as! PFFile)          
        self.postLocation.append(userPost["userPostLocation"] as! String) 
        self.postCaptions.append(userPost["postCaption"] as! String) 
        print(self.postCaptions.count) //returns value of 2 for the two posts that I've made     
        self.tableView.reloadData()    
        self.refresher.endRefreshing() 
       } 
      } 
     } 

    })   
    print(self.postCaptions.count) //Returns empty array 

は、私は問題は、スレッドの順であることを知っていると私は理解していることが、私は、アレイは、クエリの外に埋めたままにするために行うことができます正確に何かわかりません。私はこれをこの問題を解決する方法として見たことがありますが、私のコードでこの問題をどのように解決できるかについての直接的な答えは実際には見つかりませんでした。誰かが素晴らしいだろう私のコードで動作する答えを提供することができれば!:)私は一週間以上になりました

var postCaptions = [String]() { 
didSet { 
    // Do any execution that needs to wait for postCaptions here. 
} 
} 

** cellForRowAt

 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "userPhotoFeedCell", for: indexPath) as! FeedCell 

    if PFUser.current()?.objectId != nil { 

     cell.userUsername.text = PFUser.current()?.username 

    } 


    //downloads images for user profile pic 
    imageFiles[indexPath.row].getDataInBackground { (data, error) in 

     if let imageData = data { 

      let downloadedImage = UIImage(data: imageData) 

      cell.userProfilePic.image = downloadedImage 

     } 


    } 

    //downloades images and items to populate user post 
    postImageFiles[indexPath.row].getDataInBackground { (data, error) in 

     if let userPostImageData = data { 

      let downloadedUserPostImage = UIImage(data: userPostImageData) 

      cell.userFeedPhoto.image = downloadedUserPostImage 

     } 


    } 

    cell.postLocation.text = postLocation[indexPath.row] 

    cell.postCaption.text = postCaptions[indexPath.row] 

    cell.userFeedPhoto.image = UIImage(named: "OrangeFuego") 

    cell.userProfilePic.image = UIImage(named: "usericon.png") 

    return cell 

} 
+0

'非同期で動作しますfindObjectsInBackground'。印刷行は、データが返される前に実行されます。印刷行を完成ブロックに入れます。 – vadian

+0

はい、完了ブロックが読み込まれるまでnumberOfRowsInSectionの呼び出しを遅らせる必要があります。したがって、postCaptionsに値 –

+0

を与えました。 'numberOfRowsInSection'がフレームワークから呼び出されました。あなたのデータソース配列にデータを入れ、 'reloadData()'を呼び出します。 – vadian

答えて

0

た場合のために、この問題で立ち往生してきましたあなたの問題を理解しているのはむしろ単純です。希望するクラス内のグローバル変数としてvar postCaptions = [String]()を設定します。それから、あなたがやったやり方と同じように反復から値を追加します。その後、コードの他の部分でpostCaptions値にアクセスでき、countプロパティを使用できます。

+0

変数は問題ではありません。問題は、numberOfRowsInSectionが呼び出される前にfindObjectsInBackgroundが終了しないので、配列は常に0になります。 –

0

メソッドfindObjectsInBackgroundは、それがバックグラウンドで実行されることを示唆しているため、UIとは何の関係もないため、この関数が完了するまで配列は空のままです。その配列を印刷する瞬間、この関数はまだ完了していないので、今のところpostCaptionsは空になります。

また、numberOfRowsがゼロになるのはそのためです。

私はこのクエリをviewDidLoadまたは指定されたイニシャライザに配置し、完了ブロック内で行ったようにtableView.reloadData()を呼び出すことだと思います。また、Boolを宣言して、テーブルがロードされているかどうかを判断し、完了ブロックでクエリを正常に実行した後にisLoadingをfalseに設定することもできます。

query2.findObjectsInBackground(block: { (objects, error) in 

    if let userPosted = objects { 
     self.isLoading = false 

     for object in userPosted { 

      if let userPost = object as? PFObject { 

       self.postImageFiles.append(userPost["userPostImage"] as! PFFile) 

       self.postLocation.append(userPost["userPostLocation"] as! String) 

       self.postCaptions.append(userPost["postCaption"] as! String) 

       print(self.postCaptions.count) //returns value of 2 for the two posts that I've made 

      } 

     } 

     self.tableView.reloadData() 

     self.refresher.endRefreshing() 

    } 

}) 

とあなたのnumberOfRowsInSection内側:

if isLoading { //you need to declare isLoading 
    return 1 //maybe a dummy cell to tell user the table is loading 
} else { 
    return postCaptions.count 
} 
+0

私はこれを試していましたが、isLoadingはfalseにはなりませんfindObjectsInBackgroundは、NumberOfRowsInSectionが呼び出された時点で常に読み込み中です。 findObjectsInBackgroundが終了してから残りのものを呼び出すまで待つ必要があります。 –

+0

@FinnWolffおそらく 'for-in'ループの外に' reloadData() 'と' self.isLoading = false'を置くべきでしょう。上記の私の編集された答えを見てください。クエリ(バックグラウンドスレッド)が実行を完了した後に 'reloadData()'を呼び出したので、理論上は 'isLoading'は設定した後にfalseになるはずです。 'reloadData()'が呼び出されるたびに、 'numberOfRows'メソッドが呼び出されるためです。 –

+0

私はnumberOfRowsInSectionのif isLoading = false戻りpostCaptions.count部分にprint( "IT WORKED")を追加しました。それは動作しました!配列に値が設定されていますが、アプリでフィードをスクロールすると、クラッシュする: –

関連する問題