【问题标题】:Array returning an empty array outside of PFQuery with Parse使用 Parse 在 PFQuery 之外返回一个空数组的数组
【发布时间】:2017-08-30 11:15:02
【问题描述】:

我正在尝试填充数组 postCaptions。 我需要将此数组返回给我的表格视图的 numberOfRowsInSection,但它每次都返回一个空数组。

  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

}

【问题讨论】:

  • findObjectsInBackground 异步工作。在返回数据之前执行打印行。将打印行放入完成块中。
  • 是的,但我需要延迟 numberOfRowsInSection 的调用,直到完成块加载完成,因此给 postCaptions 一个值
  • numberOfRowsInSection 从框架中调用。填充您的数据源数组并调用reloadData()

标签: arrays swift parse-platform tableview pfquery


【解决方案1】:

如果我理解您的问题,那就很简单了。将var postCaptions = [String]() 设置为所需类中的全局变量。然后按照您所做的方式将迭代中的值附加到它。然后可以在代码的其他部分访问 postCaptions 值,并且可以使用 count 属性。

【讨论】:

  • 变量不是问题,问题在于findObjectsInBackground在调用numberOfRowsInSection之前永远不会结束,所以数组总是0
【解决方案2】:

由于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
}

【讨论】:

  • 我喜欢它的发展方向,但是我试过了,isLoading 永远不会等于 false,因为 findObjectsInBackground 在调用 NumberOfRowsInSection 时总是会继续加载。我需要一些方法等到 findObjectsInBackground 完成后再调用其余部分。
  • @FinnWolff 也许您应该将reloadData()self.isLoading = false 放在for-in 循环之外。请参阅上面我编辑的答案。由于您在查询(后台线程)完成执行后调用了reloadData(),所以理论上,设置后isLoading 应该为false。因为每次调用reloadData()时,都会调用numberOfRows方法。
  • 所以我在 numberOfRowsInSection 的 if isLoading = false return postCaptions.count 部分添加了 print("IT WORKED")。它确实有效!该数组已填充并且所有内容,但是当我滚动浏览应用程序中的提要时,它崩溃了,说:索引超出范围
  • 我认为填充数组并将其返回给 numberOfRowsInSection 不会导致索引超出范围错误。你知道为什么会发生这种情况吗? : /
  • @FinnWolff 你能告诉我cellForRowAtIndexPath 方法中的代码吗?我想这就是原因。
猜你喜欢
  • 1970-01-01
  • 2017-02-27
  • 1970-01-01
  • 1970-01-01
  • 2011-10-10
  • 1970-01-01
  • 2017-06-21
  • 1970-01-01
  • 2020-02-11
相关资源
最近更新 更多