在功能退出后,观察到来自Firebase的调用未更新字典的值

时间:2019-12-14 02:40:16

标签: ios swift xcode firebase

我正在尝试学习iOS编程,所以我认为模仿instagram feed是一个好主意。每个人都使用此基本提要,我想知道如何做。

基本思想是在一个栏中显示一个图像/文字帖子。现在我只显示一张图片。

我当前正在从Firebase正确提取图像URL。唯一的问题是我的CollectionView仍然显示为空。我几个月前开始了这个项目,却忘了本教程在哪里。请帮助我填补空白。这是代码:

import UIKit
import SwiftUI
import Firebase
import FirebaseUI
import SwiftKeychainWrapper

class FeedViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource{



    @IBOutlet weak var collectionview: UICollectionView!

   //var posts = [Post]()


    var posts = [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.

        posts1 = fetchPosts()
        //let myIndexPath = IndexPath(row: 0, section: 0)
        //collectionView(collectionview, cellForItemAt: myIndexPath)
        //print(self.posts1.count)
    }

    func  fetchPosts() -> [String]{
        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)

                            }
                        }

                    }
                }
            }
            })

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

    override func viewDidLayoutSubviews() {
        collectionview.reloadData()
    }
    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.
    }
    */

}

更新

观察调用未更新帖子(字典)的值。观察调用退出后,posts的值将重新设置为空。

要求的PostCell类:

import UIKit

class PostCell: UICollectionViewCell {


    @IBOutlet weak var postImage: UIImageView!
    @IBOutlet weak var authorLabel: UILabel!
    @IBOutlet weak var likeLabel:UILabel!

    @IBOutlet weak var likeBtn:UIButton!
    @IBOutlet weak var unlikeBtn:UIButton!

    @IBAction func likePressed (_ sender: Any){

    }
    @IBAction func unlikePressed(_sender: Any){

    }

}

2 个答案:

答案 0 :(得分:0)

我认为问题是: 您的collectionView数据源仅被调用一次。由于图片网址的加载是异步的,因此每次将新数据追加到数据源数组时,您都需要刷新collectionview,如下所示:

self.posts.append(urlimage)
collectionView.reloadData()

或:

var posts = [UIImage](){
didSet{
collectionView.reloadData()
}
}

希望这会有所帮助。

编辑更新: 关于异步调用,我认为您应该使用转义闭包,以便在网络请求收到响应后运行代码块。

首先将网络调用功能分开,例如:

func fetchUsers(completion: @escaping(_ dictionary: [String: NSDictionary])->()){
    let uid = Auth.auth().currentUser!.uid

    let uids = Database.database().reference().child("users")
    uids.observe(DataEventType.value, with: { (snapshot) in
        let dict = snapshot.value as! [String:NSDictionary]
        completion(dict)
    })
}

func fetchURLS(completion: @escaping(_ dictionary: [String: String])->()){
    let ref = Database.database().reference().child("posts")

    ref.observe(DataEventType.value, with: { (snapshot2) in
        let dict2 = snapshot2.value as! [String:String]
        completionTwo(dict2)
    })
}

然后,解析功能:

func parseUsers(dictionary: [String: NSDictionary]){
    for (_,value) in dictionary {
        if let uid = value["uid"] as? String{
            self.following.append(uid)
        }
    }
    fetchURLS { (urlDictionary) in
        self.parseImageURLS(dictionary: urlDictionary)
    }
}

func parseImageURLS(dictionary: [String: String]){
    for(key, value) in dictionary{
        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)

                    }
                }

            }
        }
    }
}

然后添加:

    fetchUsers { (usersDictionary) in
        self.parseUsers(dictionary: usersDictionary)
    }

viewDidLoad()

希望这可以解决您的问题。附带说明:我建议使用模型并将网络调用分隔在另一个文件中。随时问任何问题。

答案 1 :(得分:0)

更多搜索后,我想出了解决方法。

我错误地认为在viewDidLoad()函数完成后加载了CollectionView。 CollectionView的帮助程序类将调用reloadData的调用。

我观察到没有调用reloadData调用。为了完成这项工作,我向viewDidLoad函数添加了两行代码:

collectionview.delegate = self
collectionview.dataSource = self

通过此更改,现在可以加载图像。