2017-04-09 17 views
0

Ich habe ein Problem, das meiner Meinung nach kein Problem sein sollte.Swift setzt keinen Wert in Return-Anweisung

Wenn ich diese "einfache" Funktion lade, sollte es die Benutzer innerhalb der DB zurückgeben.

- returns usersDictionary: All the users in a dictionary 
*/ 
func getAllUsers() -> Dictionary<String, AnyObject> { 
    var usersDict = Dictionary<String, AnyObject>() 

    if userIsLoggedIn() == true{ 
     FIRDatabase.database().reference().child("users").observeSingleEvent(of: .value, with: { (snapshot) in 
      if let userDictionary = snapshot.value as? [String:AnyObject]{ 
       for user in userDictionary{ 

        usersDict.updateValue(user.value as AnyObject 
         , forKey: user.key as String) 


       } 
       print("TEST") 
       print(usersDict) 
      } 
      print("TEST2") 
      print(usersDict) 
     }) 
     print("TEST3") 
     print(usersDict) 
     return usersDict 

    } 
    return usersDict 
} 

Allerdings ist es nicht mit dem Wert zurückgeben usersDict, aber nur leer, was, weil es den Wert des TEST ausdruckt und TEST2 usersDict seltsam.

Aber Test3 bleibt leer, wie ist das möglich? Wenn ich in der Konsole nachschaue, macht es zuerst Test3 und dann test und dann test2. Diese

ist, was Konsole druckt:

TEST3 
[:] 
TEST 
"ZuUiTSu142P5NTc9VfekRbuFcny2": { 
    address = "testAddress"; 
    email = "[email protected]"; 
    name = "testuser"; 
    phonenumber = "1234567890"; 
    rol = Customer; 
}] 
TEST2 
"ZuUiTSu142P5NTc9VfekRbuFcny2": { 
    address = " testAddress "; 
    email = " [email protected] "; 
    name = "testuser"; 
    phonenumber = "1234567890"; 
    rol = Customer; 
}] 
+0

Es ist überhaupt nicht seltsam: 'observeSingleEvent' arbeitet ** asynchron **, die Daten werden später in der Schließung zurückgegeben. Sie benötigen einen Completion-Handler, etwas direkt zurückzugeben ist unmöglich. – vadian

+0

Mögliches Duplikat von [Zurückgeben von Daten aus einem asynchronen Aufruf in der Swift-Funktion] (http://stackoverflow.com/questions/25203556/returning-data-from-async-call-in-swift-function) – Keiwan

Antwort

0

@vadian befindet sich direkt vor Ort mit seinem Kommentar: Sie versuchen, synchron einen Wert in einer Funktion zurückzukehren, während Sie die Daten asynchron zu holen. Alles geschieht mit Ihrem // lines of code hier:

FIRDatabase.database().reference().child("users").observeSingleEvent(of: .value, with: { (snapshot) in 
    // ... 
    // lines of code 
    // ... 
}) 

asynchron geschieht. Das heißt, es passiert im Hintergrund und der Code, den Sie nach dem Aufruf observeSingleEvent haben, wird zuerst ausgeführt, daher sehen Sie TEST3 als erste Ausgabezeile.

Es gibt verschiedene Möglichkeiten, Ihren Code um eine Asynchronous Model zu gestalten. Die wahrscheinlich einfachste wäre das Weiterleiten einer Callback-Funktion, die aufgerufen wird, sobald der Async-Code die Ausführung beendet hat.

Klingt verwirrend? Mach dir keine Sorgen, es ist zunächst verwirrend, aber sobald Sie es bekommen, werden Sie erstaunt sein, wie einfach das Konzept ist.

Ich werde nicht erklären, wie Callbacks und Async funktioniert, aber ich würde Sie auf eine similar problem hinweisen, die eine sehr gute Antwort hat. Schaut es euch an und ihr solltet die Idee bekommen.

Viel Glück!

0

Vielen Dank für die Antworten, vielleicht ein bisschen zu spät, weil ich diesen Teil für eine Weile übersprungen und mich auf andere Dinge konzentriert habe, aber ich habe es heute angeschaut und es geschafft, was am Ende sehr einfach war.

func loadBusiness(busUID: String,with completion: @escaping(_ business: [String:AnyObject], _ error: NSError?) -> Void){ 
     FIRDatabase.database().reference().child("businesses").child(busUID).observeSingleEvent(of: .value, with: { (snapshot) in 
      if let busDict = snapshot.value as? [String:AnyObject]{ 
       completion(busDict, nil) 
      } 
     }) { (error) in 
      print("Error occured: " + error.localizedDescription) 
     } 
    } 

Nur ein einfaches Beispiel dafür, wie schaffe ich es zu tun, und ich kann es überall rufen jetzt mit:

// Load basic company info 
     db.loadBusiness(busUID: db.getMyUID()) { (business, error) in 
      self.myCompany = business 
     } 
Verwandte Themen