Ler Ws Ler Ws - 2 months ago 35
Swift Question

How to make uicollectionview reload once it receives data from firebase?

I would like to make a UI collectionView reload itself after it has received data from firebase. Right now it only works manually when I click on the refresh button.

class MedalsViewController: UICollectionViewController {

var imagesArray = [String]()
var identities = [String]()
var identities2 = [String]() //Creates an empty array
var imagesArrayGreyed = [String]()
var identities3 = [String]()
let databaseRef = FIRDatabase.database().reference()
let userID = FIRAuth.auth()?.currentUser?.uid

override func viewDidLoad() {
super.viewDidLoad()


let userID = FIRAuth.auth()?.currentUser?.uid
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("users").child(userID!).child("medals").observeSingleEventOfType(.Value, withBlock: { (snapshot) in
// Get user medals
self.identities3 = snapshot.value as! [String]
print (self.identities3)
})


imagesArray = ["1", "2", "3"] //Add all the medal images here
identities = ["Shield", "Tie", "Star"] //Add all the identities here
identities2 = ["Shield", "Tie"] //Choose what medals the user has.
imagesArrayGreyed = ["1Greyed","2Greyed","3Greyed"] //Add all the greyed images here

}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

override func viewWillAppear(animated: Bool) {

self.tabBarController?.tabBar.hidden = false
// Attempt at getting medals array from firebase database

}



override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath)

let imageView = cell.viewWithTag(1) as! UIImageView

// Identites2 is the medals you currently own, so it'll check back to see if you own the medal and if not a question mark will be displayed.
// Time to check to see if it can update in real time. Check out firebase and try to link it here
// Also see if can add a progress bar to only show for those greyed out medals


// Get ready to edit this to identities3 which is directly taken from firebase database
if (identities3.contains(identities[indexPath.row])) {
imageView.image = UIImage(named: imagesArray[indexPath.row])

}
else {
imageView.image = UIImage(named: imagesArrayGreyed[indexPath.row]) //Set default image not in identities2
}

return cell

}

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

override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let vc = identities[indexPath.row]
let viewController = storyboard?.instantiateViewControllerWithIdentifier(vc)
self.navigationController?.pushViewController(viewController!, animated: true)
viewController?.title = self.identities[indexPath.row]
}


// Send a fake medal from the array of identities2
@IBAction func sendFakeMedalandReload(sender: UIBarButtonItem) {
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("users/\(FIRAuth.auth()!.currentUser!.uid)/medals").setValue(identities2)
self.collectionView!.reloadData()
}
}


What this code does is basically display medals a user has by comparing two arrays (identities and identities3) to make sure they tally if not it will greyed out the images of identities no contained in the array (identities3)

The data is received in viewDidLoad as a snapshot data from firebase. I intend to make it such that the collectionView will reload every time when viewWillAppear is called.

I've attempted to call self.collectionView!.reloadData() in viewDidLoad and viewDidAppear but to no avail. I suspect it could be the delay in which data is received causing a blank array (identities3) to be loaded instead.

Answer

You need to call self.collectionView!.reloadData() after you have retrieved you data and stored it into your DataSource.

i.e in your completionBlock: of your Firebase .observeSingleEventOfType

databaseRef.child("users").child(userID!).child("medals").observeSingleEventOfType(.Value, withBlock: { (snapshot) in
        // Get user medals
        self.identities3 = snapshot.value as! [String]
        self.collectionView!.reloadData()
    })
Comments