如何在Firebase完成用户数据下载后重新加载UITableView数据?

时间:2016-09-14 09:33:57

标签: ios swift asynchronous firebase firebase-realtime-database

所以我遇到了firebase的问题,因为它是异步的,我不知道如何正确使用它。我的应用程序有待售产品,我从firebase数据库和firebase存储(图片)获得。问题是我不知道何时或如何重新加载我的UITableView以获取所有数据而不会出现nil错误。而且它更复杂,因为首先我需要从firebase获取我的salePost信息,之后我才能获得同样在tableview单元格中的用户信息。

这就是我获取salesPosts的方式

    func getSalePosts() -> [SalePost]{

    var salePosts = [SalePost]()

    FIR_DATABASE_SALE_POSTS.queryLimitedToFirst(NUMBER_OF_LOADED_POSTS).observeEventType(.Value, withBlock: { (snapshot) in

        for snap in snapshot.children{

            let imgString = snap.value["image"] as! String!
            let imgNSURL = NSURL(string: imgString)
            let imgNSDATA = NSData(contentsOfURL: imgNSURL!)

            let downloadedImg = UIImage(data: imgNSDATA!)

            let newSalePost = SalePost(title: snap.value["title"] as! String!,
                userUID: snap.value["authorUID"] as! String!,
                postBody: snap.value["body"] as! String!,
                amountAvailable: snap.value["amountAvailable"] as! String!,
                unit: snap.value["unit"] as! String!,
                price: snap.value["price"] as! String!,
                image: downloadedImg!)

            salePosts.append(newSalePost)
            print("num of posts \(salePosts.count)")
        }

    }) { (error) in
            print(error.localizedDescription)
    }

    return salePosts
}

这是获取UserInfo的func(我将从salePost对象获取“userUID”)

    func getProducer(userUID:String) -> Producer{


    var newProducer:Producer?

    FIR_DATABASE_USERS.child(userUID).observeEventType(.Value, withBlock: { (snap) in

        print(snap.description)

        let imgString = snap.value!["profilePic"] as! String!
        let imgNSURL = NSURL(string: imgString)
        let imgNSDATA = NSData(contentsOfURL: imgNSURL!)
        let downloadedImg = UIImage(data: imgNSDATA!)


        let someProducer = Producer(
            displayName: snap.value!["displayName"] as! String!,
            address: snap.value!["address"] as! String!,
            mobile: snap.value!["mobile"] as! String!,
            email: snap.value!["email"] as! String!,
            password: "",
            bio: snap.value!["bio"] as! String!,
            profilePic: downloadedImg!,
            openingHour: snap.value!["openingHour"] as! String!,
            closingHour: snap.value!["closingHour"] as! String!)

        newProducer = someProducer
        print(newProducer?.description)

        }) { (error) in
            print(error.localizedDescription)
    }

    return newProducer!
}

正如我所说,我不知道何时,何地以及如何调用这些函数(在我的Feed控制器中)使其“同步”并将所有数据都提供给tableview Cells。我将感激你的每一个帮助。我尝试谷歌,甚至在这里找到它,但没有任何帮助我。

2 个答案:

答案 0 :(得分:1)

创建所有salePosts后,您应致电tableView.reloadData()。因此,在您循环创建将newSalePost附加到salePosts的位置之后。由于这是一个异步调用,因此在函数结束时返回salePosts是没用的。

我假设您有一个viewController的属性tableView,并且您将delegate的{​​{1}}和datasource设置为{{1} }}

不要忘记在主线程上调用tableView

例如:viewController

答案 1 :(得分:0)

对于将来看到此帖子的用户,您还可以使用Dispatch组来处理从Firebase获取数据的异步属性。有关调度组工作的更多信息,请阅读Dispatch Groups in Swift 3。 Swift 4中的语法或多或少相同。这就是我用tableview实现项目调度的方法。

var anEmptyArray: [String] = []
var dbRef: DatabaseReference!

@IBOutlet weak var myTable: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()
    retrieveDataFromDatabase()
}

func retrieveDataFromDatabase() {
    dbRef = Database.database().reference().child("user")
    dbRef.observe(.value, with: { snapshot in
        let group = DispatchGroup()
        let enumerator = snapshot.children

        while let rest = enumerator.nextObject() as? DataSnapshot {
            group.enter()
            self.categories.append(rest.value as! String)
            group.leave()
        }
        group.notify(queue: .main) {
            self.categoryTable.reloadData()
        }
    })

}

我使用了snapshot.children,因为我的数据结构如何。如何获取快照取决于您拥有的结构。调度组必须在dbRef.observe关闭中使用。