Skiddswarmik
Skiddswarmik

Reputation: 236

Adding FirebaseDataSnapshot to Array as String (Swift 3)

So I am currently trying to get the number of "Posts" within my Firebase Database, but for some reason, it says that the amount equal to one (which is true) but then resets itself when calling "postNumber". I also want to keep the data in the array for later use so I kept it all in an array rather than reading straight off the Database and not storing any data at all.

viewDidLoad() Function

var postNumber = 0
override func viewDidLoad() {
        super.viewDidLoad()

        updateFeed()
        print("PostNumber in ViewDidLoad: \(self.postNumber)") //equals 0
        collectionView?.backgroundColor = .white
    }

updateFeed Function

func updateFeed(){
        let uid = FIRAuth.auth()?.currentUser?.uid
        let ref = FIRDatabase.database().reference(fromURL: "https://firebaseio.com/")

        ref.child("users").child(uid!).child("Posts").observe(.value, with: { (snapshot) in
            for item in snapshot.children{
                let snapshotValue = snapshot.value as? NSDictionary
                var snapString = String(describing: item)
                var snapInt = Int(snapString)
                self.postCollection.append(snapString)
                let firstName = (snapshot.value as! NSDictionary)["First Person"] as? String
                print("SnapShot: \(snapString)") //gives proper data
                self.postNumber = self.postCollection.count
                print("PostNumber: \(self.postNumber)") //equals 1
                print("PostSource: \(self.postCollection)")
            }
        })
        print("Number of Posts (After Adding): \(self.postCollection.count)") //equals 0
        collectionView?.reloadData()
    }

Upvotes: 1

Views: 85

Answers (2)

dst3p
dst3p

Reputation: 1038

To elaborate on the above answer, Firebase uses a completion handler or callback which allows you to do work on the data retrieved from the asynchronous call once it has been completed. In your example, because of the asynchronous operation, both of your print commands are executed before Firebase returns from the asynchronous call. Any code executed outside the Firebase completion handler runs the risk of executing before the data has been retrieved.

I would review this Firebase doc, which talks about their asynchronous operations and callback (completion handlers).

https://firebase.google.com/docs/database/ios/read-and-write

Upvotes: 0

user3476154
user3476154

Reputation:

It doesn't actually reset itself. The problem is you're calling postNumber before Firebase has a chance to replace it with 1. Firebase queries work asynchronously, basically this means your code will continue to run while Firebase is fetching the results of your query.

An easy way to show this would be by replacing your first line with this. The didSet will run every time the value of postNumber changes. This will show you in exactly which order the commands are executed.

var postNumber = 0 {
  didSet {
    print(postNumber)
  }
}

And if you're using postCollection to fill up your collectionView you can use

var postCollection = [String]() {
  didSet {
    collectionView?.reloadData()
  }
}

You can leave the rest of your code as is, this should give you a basic understanding of what async is. With some googling you should be able to find elegant ways to deal with asynchronous code.

Async vs. synchronous

Upvotes: 1

Related Questions