2017-03-13 38 views
1

我有一个收集视图,显示从我的一个视图控制器中的Firebase中获取的图像,FeedViewController - 在该控制器中viewDidLoad我使用fetchPosts函数获取图像(我也删除提取之前的所有帖子否则会出现两次 - 让我知道这是不是这样做的一个很好的方式):从一次调用中获取两次Firebase数据

override func viewDidLoad() { 
    super.viewDidLoad() 

    posts.removeAll() 
    following.removeAll() 
    fetchPosts() 
} 

我有几个“秀”塞格斯到FeedViewController,所有这些做工精细,饲料负载,因为它应该 - 所有图像都会出现一次。但是,我有一个在用户选择要上传图像后调用的segue,它以某种方式导致图像被提取(因此出现在CV中)两次。该SEGUE被称为在上传功能在这里:

func uploadToFirebase() { 
    AppDelegate.instance().showActivityIndicator() 

    let uid = FIRAuth.auth()!.currentUser!.uid 
    let ref = FIRDatabase.database().reference() 
    let storage = FIRStorage.storage().reference(forURL: "gs://cloudcamerattt.appspot.com") 
    let key = ref.child("posts").childByAutoId().key 
    let imageRef = storage.child("posts").child(uid).child("\(key).jpg") 
    let data = UIImageJPEGRepresentation(self.previewImage.image!, 0.6) 
    let uploadTask = imageRef.put(data!, metadata: nil) { (metadata, error) in 
     if error != nil { 
      print(error!.localizedDescription) 
      AppDelegate.instance().dismissActivityIndicator() 
      return 
     } 
     imageRef.downloadURL(completion: { (url, error) in 

      if let url = url { 
       let feed = ["userID" : uid, 
          "pathToImage" : url.absoluteString, 
          "likes" : 0, 
          "author" : FIRAuth.auth()!.currentUser!.displayName!, 
          "postID" : key] as [String : Any] 

       let postFeed = ["\(key)" : feed] 
       ref.child("posts").updateChildValues(postFeed) 
       AppDelegate.instance().dismissActivityIndicator() 

       self.performSegue(withIdentifier: "showFeed", sender: nil) 
      } 
     }) 
    } 
    uploadTask.resume() 
} 

这似乎是SEGUE是在函数中的正确位置(再纠正我,如果我错了),但就像我说的,当用户选择一个图像并点击发布按钮,上述功能被调用,它们被带回到馈送控制器,并且他们发布的图像以及当前在馈送中的所有其他图像将显示两次(有时是三次)。我不知道为什么会发生这种情况。如果我从饲料中导航并返回(通过其他赛段饲料),图像将再次正确显示 - 即所有图像只出现一次。

因此,由于其他赛门铁克正常工作,我觉得问题不在赛段,或在方式FeedViewController处理取得&填充CV(虽然它可能是低效率)。它必须位于上传功能中。就像我说的,我看不到更多合乎逻辑的地方来调用该函数中的segue。任何人都可以看到我在这里失踪?

编辑:我fetchPosts()功能:

func fetchPosts() { 

    var posts = [Post]() 

    let ref = FIRDatabase.database().reference() 
    ref.child("users").queryOrderedByKey().observe(.value, with: { snapshot in 

     let users = snapshot.value as! [String : AnyObject] 

     for (_, value) in users { 
      // get uid as string 
      if let uid = value["uid"] as? String { 
       // check to make sure uids match 
       if uid == FIRAuth.auth()?.currentUser?.uid { 
        // check for followers 
        if let followingUsers = value["following"] as? [String : String] { 
         // loop through those and add them to "following" array 
         for (_, user) in followingUsers { 
          self.following.append(user) 
         } 
        } 
        // add current user to that array also so you can see your own posts 
        self.following.append(FIRAuth.auth()!.currentUser!.uid) 

        ref.child("posts").queryOrderedByKey().observe(.value, with: { (snap) in 

         let postsSnap = snap.value as! [String : AnyObject] 

         for (_, post) in postsSnap { 
          if let userID = post["userID"] as? String { 
           for each in self.following { 
            if each == userID { 
             // here are the posts that the user should see (his own and his following) 
             let posst = Post() 
             if let author = post["author"] as? String, let likes = post["likes"] as? Int, let pathToImage = post["pathToImage"] as? String, let postID = post["postID"] as? String { 

              posst.author = author 
              posst.likes = likes 
              posst.pathToImage = pathToImage 
              posst.postID = postID 
              posst.userID = userID 
              if let people = post["peopleWhoLike"] as? [String : AnyObject] { 
               for (_, person) in people { 
                posst.peopleWhoLike.append(person as! String) 
               } 
              } 
              posts.append(posst) 
             } 
            } 
           } 
           self.collectionView.reloadData() 
          } 
         } 
        }) 
        ref.removeAllObservers() 
       } 
      } 
     } 
    }) 
} 
+0

你能告诉我们fetchPosts()方法吗?请把它写在你的问题上。 –

+0

@PieterLaebens刚刚添加了它 - 虽然就像我说的,问题只发生在从上传控制器中退出时,图像从其他控制器中获取并加载完美时,这就是为什么我认为问题必须在上传功能中。 – KingTim

+0

尝试在帖子引用中使用'.observeSingleEvent'而不是'observe',看看这是否会改变任何内容,无论如何您似乎都会移除监听器。 –

回答

2

当您使用.observe它会继续监视更改。所以我假设你只需要一次数据就可以使用removeAllObservers。在这种情况下,最好使用.observeSingleEvent,因为那样只会获取一次数据。

这是我认为正在发生的事情,很难说没有看到代码执行。由于Firebase是异步的,因此代码会继续执行并且不会等待Firebase命令完成。我认为在updateChildValues实际完成之前,您已经继续使用Feed。抵达FeedViewController之后,您清空了您的集合并加载了数据。数据将开始加载,并且在加载时,该帖子将被添加。这又触发了.value,因为数据库中的内容发生了变化,导致它多次运行。由于您只清除了viewDidLoad中的集合,所以重复的帖子将会追加到您的集合中。

为了避免这种情况,与observeSingleEvent或代替你的viewDidLoad使用removeAll()更换.observe,使用它的里面你.observe(虽然你不得不做它的主队列,我认为)。

+0

非常感谢您的回答和解答!这听起来像是发生了什么事情,因为在继续回到饲料控制器之后,会有一秒的延迟,然后CV会加载所有重复的照片。 – KingTim