Reputation: 399
I'm fairly certain my function to get data from Firebase is working correctly, however I can't display the data in the ViewController. It seems the View is rendered before the function is completed.
I need help figuring out how to run the function before the view is rendered.
This is the code in the viewController
import UIKit
import Firebase
import Kingfisher
class activityVC: UIViewController {
// Variables passed from feedVC
var activityId = ""
@IBOutlet weak var distance: UILabel!
@IBOutlet weak var time: UILabel!
@IBOutlet weak var elevation: UILabel!
@IBOutlet weak var kills: UILabel!
@IBOutlet weak var sightings: UILabel!
@IBOutlet weak var ration_shot_sightings: UILabel!
@IBOutlet weak var activityImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Get userdata from Firebase
DataService.instance.getActivityData(activityId: activityId) { (activityData) in
print("activity data dump in ViewController")
dump(activityData)
if activityData.isEmpty == false {
print("Data is coming")
// if data exist populate textfields with information from database
self.kills.text = activityData[0].name
self.sightings.text = String(activityData[0].sightingCount)
print("SightingsCount: \(activityData[0].sightingCount)")
self.kills.text = String(activityData[0].killCount)
self.sightings.text = String(activityData[0].sightingCount)
if activityData[0].defaultImageURL.isEmpty == false {
self.activityImageView.kf.setImage(with: URL.init(string:activityData[0].defaultImageURL))
}
}
}
}
// ----------------------------
// IBActions
// ----------------------------
@IBAction func backBtnWasPressed(_ sender: Any) {
// Navigates back to feedVC
self.dismiss(animated: true, completion: nil)
}
}
This is the DataService function that it runs (note I've slimmed down the function so not all variables are there)
// Get data on specific activity
func getActivityData(activityId: String, handler: @escaping (_ activities: [Activity]) -> ()) {
var activityData = [Activity]()
REF_ACTIVITY.child(activityId).observeSingleEvent(of: .value) { (snapshot) in
guard let activity = snapshot.value as? NSDictionary else { return }
let activityId = activityId
let name = activity["name"] as? String ?? ""
let description = activity["description"] as? String ?? ""
let userId = activity["userId"] as? String ?? ""
let tempKillCount = activity["killCount"] as? NSNumber ?? 0
let killCount = Int(tempKillCount)
let tempSightingCount = activity["sightingCount"] as? NSNumber ?? 0
let sightingCount = Int(tempSightingCount)
let data = Activity(activityId: activityId, name: name, userId: userId, killCount: killCount, sightingCount: sightingCount)
activityData.append(data)
print("Within function - print activityData: ")
dump(activityData)
}
handler(activityData)
}
Upvotes: 1
Views: 809
Reputation: 18630
you need to move the call to your closure (handler) in side the observe listener
observeSingleEvent
is async which means it will return immediately then this line will executed handler(activityData)
and at that moment activityData
is empty
func getActivityData(activityId: String, handler: (activities: [Activity]) -> Void )
{
var activityData = [Activity]()
REF_ACTIVITY.child(activityId).observeSingleEvent(of: .value)
{
(snapshot) in
guard let activity = snapshot.value as? NSDictionary else { return }
let activityId = activityId
let name = activity["name"] as? String ?? ""
let description = activity["description"] as? String ?? ""
let userId = activity["userId"] as? String ?? ""
let tempKillCount = activity["killCount"] as? NSNumber ?? 0
let killCount = Int(tempKillCount)
let tempSightingCount = activity["sightingCount"] as? NSNumber ?? 0
let sightingCount = Int(tempSightingCount)
let data = Activity(activityId: activityId, name: name, userId: userId, killCount: killCount, sightingCount: sightingCount)
activityData.append(data)
print("Within function - print activityData: ")
dump(activityData)
handler(activityData)
}
}
Upvotes: 1
Reputation: 100549
You can achieve this with loading the data and once it's complete push your new VC setted with downloaded data but this is not a good UX one good way to do is Cover the view of the VC with a loading indicator until the request finish and remove the activity indicator and set the data to the labels
Upvotes: 0