pranavhgupta
pranavhgupta

Reputation: 143

Accessing a variable outside closure Swift3

I have declared requestPostArray right at the beginning of the ViewController class. I'm trying to populate the requestPostArray from the database "Request Posts" and then populate the tableView from the requestPostArray. However when I print it's size it shows up to be 0. Any help would be appreciated.

Also, the entire else statement below is inside another closure.

else {

            ref.child("Request Posts").observe(.value, with: { (snapshot) in
                let count = Int(snapshot.childrenCount)

                // Request Post database is empty
                if count == 0 {
                    cell.nameLabel.text = "No requests so far."
                    cell.userNameLabel.isHidden = true
                    cell.numberOfRequestsLabel.isHidden = true
                }

                // Request Post data is populated
                else {

                    var requestPostArray: [RequestPost]? = []
                    self.ref.child("Request Posts").observe(.value, with: { (snapshot) in
                        if let result = snapshot.children.allObjects as? [FIRDataSnapshot] {

                            for child in result {
                                let post = RequestPost(snapshot: child)
                                requestPostArray?.append(post)
                            }
                        }

                        else {
                            print("No Result")
                        }
                    })


                    print("RequestPostArray size = \(requestPostArray?.count ?? 90)")

                    cell.nameLabel.text = self.requestPostArray?[indexPath.row].name
                    cell.userNameLabel.text = self.requestPostArray?[indexPath.row].name
                    cell.numberOfRequestsLabel.text = self.requestPostArray?[indexPath.row].name
                }
            })
        }

Upvotes: 0

Views: 378

Answers (2)

Achref Gassoumi
Achref Gassoumi

Reputation: 1056

this is what should happens because observe function is asynchronous and the rest of your code is synchronous, in addition if you remove the optional unwrap from requestPostArray? you will get a nil exception because the async task needs time to get executed so the compiler will execute the snyc task before it. basically what you have to do is the following

 else {

                ref.child("Request Posts").observe(.value, with: { (snapshot) in
                    let count = Int(snapshot.childrenCount)

                    // Request Post database is empty
                    if count == 0 {
                        cell.nameLabel.text = "No requests so far."
                        cell.userNameLabel.isHidden = true
                        cell.numberOfRequestsLabel.isHidden = true
                    }

                    // Request Post data is populated
                    else {

                        var requestPostArray: [RequestPost]? = []
                        self.ref.child("Request Posts").observe(.value, with: { (snapshot) in
                            if let result = snapshot.children.allObjects as? [FIRDataSnapshot] {

                                for child in result {
                                    let post = RequestPost(snapshot: child)
                                    requestPostArray?.append(post)
                                }
                            }

                            else {
                                print("No Result")
                            }
print("RequestPostArray size = \(requestPostArray?.count ?? 90)")

                        cell.nameLabel.text = self.requestPostArray?[indexPath.row].name
                        cell.userNameLabel.text = self.requestPostArray?[indexPath.row].name
                        cell.numberOfRequestsLabel.text = self.requestPostArray?[indexPath.row].name
                        })



                    }
                })
            }

another advice think about using singleton so you can gain the reuse of your object and you will not invoke the database several time at the same method like you are doing now.

Upvotes: 1

Jonah
Jonah

Reputation: 17958

observe blocks are asynchronous. You're reading requestPostArray before it has been modified by your requestPostArray?.append(post) line.

Without more context it's hard to know how you want to be populating values on this cell object but if you need "Request Posts" then you have to wait until you've been able to obtain them.

Upvotes: 3

Related Questions