Как мне показать данные, полученные из Firebase, на контроллере представления, который находится внутри контроллера панели вкладок? - PullRequest
0 голосов
/ 01 августа 2020

У меня есть ViewController, в котором я хотел бы показать индикатор активности при получении данных имени пользователя из firebase и изменении имени пользователя в MenuViewController. После этого отобразится MenuViewController. Но проблема, с которой я столкнулся, заключается в том, что строка "menuV C .greetText =" Hi "+ username" не работает. В ViewController не отображается имя пользователя. Любой совет приветствуется. Заранее спасибо.

class LoadingViewController: UIViewController {
@IBOutlet var activityIndicator: UIActivityIndicatorView!

override func viewDidLoad() {
    super.viewDidLoad()
    startLoading {
        switchToMenu()
    }
    // Do any additional setup after loading the view.
}


func startLoading(finished: () -> Void) {
    
    activityIndicator.startAnimating()
    
    authenticateUserAndConfigureView()
    
    finished()
    
    activityIndicator.stopAnimating()
    
}

func switchToMenu() {
    
    DispatchQueue.main.async {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let mainViewController  = storyboard.instantiateViewController(identifier: "MainVC")
    self.view.window?.rootViewController = mainViewController
    
    self.view.window?.makeKeyAndVisible()
     
    }
    
}

func authenticateUserAndConfigureView() {

    if Auth.auth().currentUser == nil {
        DispatchQueue.main.async {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let loginController  = storyboard.instantiateViewController(identifier: "LoginViewController")
        self.view.window?.rootViewController = loginController
        
        self.view.window?.makeKeyAndVisible()
         
        }
    }
    else {
        //let tabBar = segue.destination as! UITabBarController
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let tabBar  = storyboard.instantiateViewController(identifier: "MainVC") as! UITabBarController
        let menuVC = tabBar.viewControllers?[0] as! MenuViewController
            
        guard let uid = Auth.auth().currentUser?.uid else {return}
            
        Database.database().reference().child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
            let value = snapshot.value as? NSDictionary
            let username = value?["Username"] as? String ?? ""
            menuVC.greetText = "Hi " + username
            }
            )
            
            
        }
        
    }
}

1 Ответ

0 голосов
/ 01 августа 2020

Здесь вы имеете дело с функцией asynchronous, и вы также находитесь внутри closure, что означает, что как только вы покинете закрытие, присвоенные значения внутри закрытия будут недоступны. Вам нужно completionHandler, чтобы разобраться с этим. Вы можете сделать из него отдельную функцию, а затем вызвать ее внутри authenticateUserAndConfigureView.

func getName(completion:@escaping((String)->()) {
     Database.database().reference().child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
            let value = snapshot.value as? NSDictionary
            let username = value?["Username"] as? String ?? ""
            completion(name)
          }

И затем вы можете вызвать эту функцию следующим образом.

getName{(nameOfUser) in
     print("Name is \(nameOfUser)")
  }

В вашем случае:

Звонок внутри authenticateUserAndConfigureView

func authenticateUserAndConfigureView() {
if (......) {
  //All your code
}
else {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let tabBar  = storyboard.instantiateViewController(identifier: "MainVC") as! UITabBarController
        let menuVC = tabBar.viewControllers?[0] as! MenuViewController
            self.getName{(name) in
            menuVC.greetText = "Hi" + name       
     }
     
  }

}

Возможно, вам понадобится использовать DispatchQueue для возможной проблемы timing, но я не уверен в этом. Если да, дайте мне знать.

...