2017-12-27 1059 views
1

我试图从observeSingleEvent获得某个名为City的子节点,但我在试图将其拉入主线程中时出现问题。我使用了完成处理程序和调度调用的组合,但我不确定我在做什么错误,除了在异步方面没有那么好。在viewDidLoad我试图从setupSavedLocations函数追加我的密钥,并将它返回给savedLocations我觉得我很接近。我错过了什么?不知道如何在异步调用之外追加数组

编辑:净度上的问题

import UIKit 
import Firebase 

class SavedLocationsViewController: UIViewController { 

    var userID: String? 
    var savedLocations: [String] = [] 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     setupSavedLocations() { (savedData) in 
      DispatchQueue.main.async(execute: { 
       self.savedLocations = savedData 
       print("inside", self.savedLocations) 
      }) 
     } 
     print("outside",savedLocations) 
    } 

     func setupSavedLocations(completion: @escaping ([String]) ->()) { 
     guard let user = userID else { return } 
     let databaseRef = Database.database().reference(fromURL: "https://************/City") 
     var dataTest : [String] = [] 
     databaseRef.observeSingleEvent(of: .value, with: {(snapshot) in 
      let childString = "Users/" + user + "/City" 
      for child in snapshot.children { 
       let snap = child as! DataSnapshot 
       let key = snap.key 
       dataTest.append(key) 
      } 
      completion(dataTest) 
     }) 
    } 

样本输出

outside [] 
inside ["New York City", "San Francisco"] 
+0

您的代码没有显示任何错误。无论如何,只需稍加观察,您可能需要在'main.async'前面指定'savedLocations':'self.savedLocations = savedData DispatchQueue.main.async'中的setupSavedLocations(){(savedData),然后如果需要刷新一些组件,例如:'UITableView',你必须在'main.async'里面执行它 –

+0

在main.async之外有什么理由?这是否意味着无法在主线程上使用我的savedLocation? – LampPost

+0

你的意思是“试图将其拉入主线程的问题”?如果您引用的是“外部”打印语句未列出位置,那是因为它在setupSavedLocations完成之前正在调用。它是异步的,所以它在运行时不会阻止你的viewDidLoad。 – ghostatron

回答

1

setupSavedLocations的调用是异步的,并且需要运行较长时间比它的CPU来完成viewDidLoad这就是为什么你的数据没有被显示。你也可以从你的输出中注意到,在inside之前调用outside表明这一点。处理这种情况的正确方法是向用户显示他们需要等待IO调用,然后在下面显示相关信息时向他们显示相关信息。

class SavedLocationsViewController: UIViewController { 

    var myActivityIndicator: UIActivityIndicatorView? 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     setupSavedLocations() { (savedData) in 
      DispatchQueue.main.async(execute: { 
       showSavedLocations(locations: savedData) 
      }) 
     } 
     // We don't have any data here yet from the IO call 
     // so we show the user an indicator that the call is 
     // being made and they have to wait 

     let myActivityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)   
     myActivityIndicator.center = view.center   
     myActivityIndicator.startAnimating() 
     self.view.addSubview(myActivityIndicator) 
     self.myActivityIndicator = myActivityIndicator 
    } 

    func showSavedLocations(locations: [String]) { 
     // This function has now been called and the data is passed in. 
     // Indicate to the user that the loading has finished by 
     // removing the activity indicator 
     myActivityIndicator?.stopAnimating() 
     myActivityIndicator?.removeFromSuperview() 

     // Now that we have the data you can do whatever you want with it here 
     print("Show updated locations: \(locations)") 
    } 
相关问题