观察呼叫未更新字典值。异步问题

时间:2019-12-14 18:04:20

标签: ios swift firebase firebase-realtime-database

我正在尝试从我的Firebase数据库中获取图像列表。在观察方法内部,如果我打印帖子数,则它可以正常工作。如果在观察函数外部打印帖子数,但仍在fetchPosts()函数内部,则得到0。如果在fetchPosts()调用(使用观察函数的函数)之后打印帖子数,则得到0。

如何在异步调用中将值保存到字典中?我试过完成和调度组。我可能没有正确实施它们,因此,如果您看到一种简单的方法,请帮助我。这是代码:

import UIKit
import SwiftUI
import Firebase
import FirebaseUI
import SwiftKeychainWrapper

class FeedViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource{


    @IBOutlet weak var collectionview: UICollectionView!

   //var posts = [Post]()


    var posts1 = [String](){
    didSet{
    collectionview.reloadData()
    }
    }
    var following = [String]()
    //var posts1 = [String]()
    var userStorage: StorageReference!
    var ref : DatabaseReference!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        fetchPosts()


    }

//    func lengthyTask(completionHandler: (Int) -> Int)
//    {
//        let result = completionHandler(42)
//        print(result)
//    }
//
//    lengthyTask(completionHandler: { number in
//        print(number)
//        return 101
//    })
//
    func  fetchPosts() {
        let uid = Auth.auth().currentUser!.uid
        let ref = Database.database().reference().child("posts")
        let uids = Database.database().reference().child("users")
        uids.observe(DataEventType.value, with: { (snapshot) in
            let dict = snapshot.value as! [String:NSDictionary]
            for (_,value) in dict {
                if let uid = value["uid"] as? String{
                    self.following.append(uid)
                }
            }
        ref.observe(DataEventType.value, with: { (snapshot2) in
            let dict2 = snapshot2.value as! [String:NSDictionary]
            for(key, value) in dict{
                for uid2 in self.following{
                    if (uid2 == key){
                        for (key2,value2) in value as! [String:String]{
                            //print(key2 + "this is key2")
                            if(key2 == "urlToImage"){
                                let urlimage = value2
                                //print(urlimage)
                                self.posts1.append(urlimage)
                                self.collectionview.reloadData()
                                print(self.posts1.count)

                            }
                        }

                    }
                }
            }
            })
            self.collectionview.reloadData()
        })
    //ref.removeAllObservers()
    //uids.removeAllObservers()
    print("before return")
    print(self.posts1.count)


    //return self.posts1
    }
    func numberOfSections(in collectionView: UICollectionView) ->Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return posts1.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PostCell", for: indexPath) as! PostCell
        cell.postImage.sd_setImage(with: URL(string: posts1[indexPath.row]))
        //creating the cell
        //cell.postImage.downloadImage(from: self.posts[indexPath.row])
//        let storageRef = Storage.storage().reference(forURL: self.posts[indexPath.row].pathToImage)
//
//
        print("im trying")

        //let stickitinme = URL(fileURLWithPath: posts1[0])
        //cell.postImage.sd_setImage(with: stickitinme)

        //cell.authorLabel.text = self.posts[indexPath.row].author
        //cell.likeLabel.text = "\(self.posts[indexPath.row].likes) Likes"

        return cell
    }


    @IBAction func signOutPressed(_sender: Any){
           signOut()
           self.performSegue(withIdentifier: "toSignIn", sender: nil)
       }

    @objc func signOut(){
           KeychainWrapper.standard.removeObject(forKey:"uid")

           do{
               try Auth.auth().signOut()
           } catch let signOutError as NSError{
               print("Error signing out: %@", signOutError)
           }
           dismiss(animated: true, completion: nil)
       }


    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}

1 个答案:

答案 0 :(得分:1)

您只需要进行一些改动

  1. 简单地声明posts1

    var posts1 = [String]()
    

    并删除属性观察者didSet

  2. self.collectionview.reloadData()之后删除行self.posts1.append(..

  3. 将上一次出现的self.collectionview.reloadData()向上移动一个级别,将其包装在DispatchQueue块中以更新主线程上的集合视图,并删除之后的print行外封

               }
               DispatchQueue.main.async {
                   self.collectionview.reloadData()
               }
            })
        })
    }
    
  4. 第二个封口中有一个错字。一定是

    let dict2 = snapshot2.value as! [String:NSDictionary]
    for(key, value) in dict2 {
    

    带有尾随索引的变量名称很容易出错,例如userDictpostDict

编辑

这是具有执行顺序的代码

override func viewDidLoad() {
    super.viewDidLoad()
    collectionview.dataSource = self
    collectionview.delegate = self
    // 1
    fetchPosts()
    // 5 
}

func fetchPosts() {
    // 2       
    let uid = Auth.auth().currentUser!.uid
    let ref = Database.database().reference().child("posts")
    let uids = Database.database().reference().child("users")
    // 3
    uids.observe(DataEventType.value, with: { (snapshot) in
        // 6
        let dict = snapshot.value as! [String:NSDictionary]
        for (_,value) in dict {
            if let uid = value["uid"] as? String{
                self.following.append(uid)
            }
        }
        // 7
        ref.observe(DataEventType.value, with: { (snapshot2) in
            // 9
            let dict2 = snapshot2.value as! [String:NSDictionary]
            for(key, value) in dict2 { // TYPO!!!!
                for uid2 in self.following{
                    if (uid2 == key){
                       for (key2,value2) in value as! [String:String]{
                            //print(key2 + "this is key2")
                            if(key2 == "urlToImage"){
                                let urlimage = value2
                                //print(urlimage)
                                self.posts1.append(urlimage)
                                print(self.posts1.count)

                            }
                       }

                    }
                }
            }
            DispatchQueue.main.async {
               // 11
               self.collectionview.reloadData()
            }
            // 10
        })
        // 8
    })
    // 4
}