Ios 如何在ViewDidLoad之前完成函数

Ios 如何在ViewDidLoad之前完成函数,ios,swift,firebase,firebase-realtime-database,uiviewcontroller,Ios,Swift,Firebase,Firebase Realtime Database,Uiviewcontroller,我相当确定我从Firebase获取数据的功能工作正常,但是我无法在ViewController中显示数据。看起来视图是在函数完成之前呈现的 在呈现视图之前,我需要帮助了解如何运行该函数 这是viewController中的代码 import UIKit import Firebase import Kingfisher class activityVC: UIViewController { // Variables passed from feedVC var activi

我相当确定我从Firebase获取数据的功能工作正常,但是我无法在ViewController中显示数据。看起来视图是在函数完成之前呈现的

在呈现视图之前,我需要帮助了解如何运行该函数

这是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)
    }
}
这是它运行的DataService函数(注意,我已经精简了该函数,因此并非所有变量都存在)


您可以通过加载数据来实现这一点,并在加载完成后推送新的VC设置下载的数据,但这不是一个好的UX方法,一个好的方法是在请求完成之前用加载指示器覆盖VC的视图,删除活动指示器并将数据设置为标签

您需要将调用移动到观察侦听器中的闭包(处理程序)

observeSingleEvent
是异步的,这意味着它将立即返回,然后该行将执行
handler(activityData)
,此时
activityData
为空

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)

    }   

}

隐藏所有标签并添加活动指示器,直到数据加载,然后在加载时显示带有firebase数据的标签。如果对firebase的调用已超时,只需进行一次测试即可从数据库调用数据。从
dump(activityData)
@Ali获得的信息:activityData为空(-0个元素),那么如果
activityData
为空,您希望如何显示数据<代码>活动数据为空表示您没有data@Ali这是一个很好的观点-我只是不明白为什么它是空的-如果我在函数中转储“activityData”,那么它会给出预期的数据。但如果我在ViewController中执行此操作,它将为空。在终端中,函数转储在ViewController中的转储之后写入。-基于此,我假设该函数是在viewControllernever认为处理程序(activityData)位于错误位置之后运行的。非常感谢你帮我做这件事。
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)

    }   

}