2017-07-23 22 views
12

Tworzę prostą aplikację do czatu, aby poznać zasady Swift i Firebase. Mam zapytanie sprawdzające, czy wiadomości z pokoju rozmów są ładowane do tableView. Zapytanie zwraca migawkę, ale mam problemy z uzyskaniem danych do zapisania i załadowania poprawnie. I stworzył słownik z migawki, dzięki czemu można uzyskać poszczególne wartości dziecka, ale one wracają nil:Zrzut ekranu Firebase Query zero?

query.observeSingleEvent(of: .childAdded, with: { snapshot in 

      print(snapshot) 

      let indexPaths = self.messages.enumerated().map { 
       IndexPath(row: $0.0, section: 0) 
      } 

      guard let messagesDict = snapshot.value as? [String:AnyObject] else { return } 
      guard let sender = messagesDict["sender"] as? String else { return } 
      guard let text = messagesDict["text"] as? String else { return } 
      guard let timestamp = messagesDict["timestamp"] as? Int else { return } 

      let message = Message.init(key: snapshot.key, sender: sender as! String, text: text as! String, timestamp: timestamp) 

      self.messages.append(message) 

      self.tableView.reloadData() 
     }) 

po messagesDict zwraca dane przy zerwaniu:

▿ 1 element 
    ▿ 0 : 2 elements 
    - key : "-KotqLUUucaRagTRt967" 
    ▿ value : 3 elements 
     ▿ 0 : 2 elements 
     - key : sender 
     - value : eGTYRSo81JefgasYLRHUFHUTnEC3 
     ▿ 1 : 2 elements 
     - key : text 
     - value : test 
     ▿ 2 : 2 elements 
     - key : timestamp 
     - value : 1499914135546 

Aplikacja pobiera do następnego przerwania gdzie Ustawiłem guard let sender, ale wyniki aplikacji powracają i przestają wykonywać resztę bloku kodu. Jak poprawnie uzyskać dostęp do elementów nadawcy, tekstu i znacznika czasu, aby móc ustawić je na zmienne i zapisać je w tablicy dla mojej tabeli?

Każda pomoc zostanie bardzo doceniona. Utknąłem na tym przez chwilę i mogłem użyć kolejnej pary oczu!

Dzięki!

Dodatkowe informacje:

Zapytanie:

let query = rootRef.child("chat-messages/\(chatKey)")

struktura bazy danych:

{ 
    "chat-messages" : { 
    "-KotqKI4zF9cS5XMR9WU" : { 
     "-KotqLUUucaRagTRt967" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914135546 
     } 
    }, 
    "-KotqvBoFFzOTY6Q1fO7" : { 
     "-KotqwGAJ85NuAp-Lh3Z" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914290279 
     } 
    }, 
    "-KotsNgF0ou5MIDn2l5K" : { 
     "-KotsOSXw7OS_3xuXZgP" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914671997 
     }, 
     "-KotsPqrCpipMLulNNFl" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test44", 
     "timestamp" : 1499914677715 
     } 
    }, 
    "-Kotsv1Vv19dEF2q7XQu" : { 
     "-KotsvYO9JvLY8gdTnA0" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914811675 
     }, 
     "-KotsvxKXzIwbyvbwLPp" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914813335 
     }, 
     "-Kotsw9vLiEf6KquU__e" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914814205 
     }, 
     "-KotswHnzmfkEXih1O7y" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914814709 
     }, 
     "-KotszHKBt254jZnUMAl" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test46456", 
     "timestamp" : 1499914826967 
     } 
    }, 
    "-KoyheS01YxWExSNxl_H" : { 
     "-Koyhf3G-FPEDrxQOcpU" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499995746607 
     } 
    }, 
    "-Koyjc_aBaF1kFE-8Bll" : { 
     "-Koyjd9PnO6sPOhS7P27" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499996263096 
     }, 
     "-KoyjdzSEi5twTVQMGOu" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499996266491 
     }, 
     "-Koyje2C9E524kV7nhLY" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499996266730 
     } 
    }, 
    "-KpfUGw45F1FU2IrR87A" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1500746948396 
    }, 
    "-KpfUHQGuTDi4yZutS5K" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1500746950368 
    }, 
    "-KpfUHdSXeTzauATsDAP" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1500746951277 
    }, 
    "-Kpfia0fXsoqpRtIr1kU" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "gerg", 
     "timestamp" : 1500750962815 
    } 
    }, 
    "chat-participants" : { 
    "-KotqKI4zF9cS5XMR9WU" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-KotqvBoFFzOTY6Q1fO7" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-KotsNgF0ou5MIDn2l5K" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-Kotsv1Vv19dEF2q7XQu" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-KoyheS01YxWExSNxl_H" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-Koyjc_aBaF1kFE-8Bll" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-KpfLBjQdPiX2kSrl1yF" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    } 
    }, 
    "chats" : { 
    "-KotqKI4zF9cS5XMR9WU" : { 
     "currentName" : "test", 
     "date" : 1499914130657 
    }, 
    "-KotqvBoFFzOTY6Q1fO7" : { 
     "currentName" : "test", 
     "date" : 1499914285904 
    }, 
    "-KotsNgF0ou5MIDn2l5K" : { 
     "currentName" : "test", 
     "date" : 1499914668844 
    }, 
    "-Kotsv1Vv19dEF2q7XQu" : { 
     "currentName" : "test", 
     "date" : 1499914809570 
    }, 
    "-KoyheS01YxWExSNxl_H" : { 
     "currentName" : "test", 
     "date" : 1499995744095 
    }, 
    "-Koyjc_aBaF1kFE-8Bll" : { 
     "currentName" : "test", 
     "date" : 1499996260740 
    }, 
    "-KpfLBjQdPiX2kSrl1yF" : { 
     "currentName" : "test3222", 
     "date" : 1500744567786 
    } 
    }, 
    "user-chats" : { 
    "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "-KotqKI4zF9cS5XMR9WU" : { 
     "chatKey" : "-KotqKI4zF9cS5XMR9WU", 
     "currentName" : "test" 
     }, 
     "-KotqvBoFFzOTY6Q1fO7" : { 
     "chatKey" : "-KotqvBoFFzOTY6Q1fO7", 
     "currentName" : "test" 
     }, 
     "-KotsNgF0ou5MIDn2l5K" : { 
     "chatKey" : "-KotsNgF0ou5MIDn2l5K", 
     "currentName" : "test" 
     }, 
     "-Kotsv1Vv19dEF2q7XQu" : { 
     "chatKey" : "-Kotsv1Vv19dEF2q7XQu", 
     "currentName" : "test" 
     }, 
     "-KoyheS01YxWExSNxl_H" : { 
     "chatKey" : "-KoyheS01YxWExSNxl_H", 
     "currentName" : "test" 
     }, 
     "-Koyjc_aBaF1kFE-8Bll" : { 
     "chatKey" : "-Koyjc_aBaF1kFE-8Bll", 
     "currentName" : "test" 
     }, 
     "-KpfLBjQdPiX2kSrl1yF" : { 
     "chatKey" : "-KpfLBjQdPiX2kSrl1yF", 
     "currentName" : "test3222" 
     } 
    } 
    }, 
    "user-friends" : { 
    "36HDn5XyxjMCcMluJJ9KPBOCDMm1" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "36HDn5XyxjMCcMluJJ9KPBOCDMm1" : { 
     "username" : "tester2" 
     } 
    } 
    }, 
    "user-invites" : { 
    "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "36HDn5XyxjMCcMluJJ9KPBOCDMm1" : { 
     "username" : "tester2" 
     } 
    } 
    }, 
    "users" : { 
    "36HDn5XyxjMCcMluJJ9KPBOCDMm1" : { 
     "email" : "[email protected]", 
     "username" : "tester2" 
    }, 
    "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "email" : "[email protected]", 
     "username" : "tester" 
    } 
    } 
} 
+0

Jakie jest Twoje zapytanie? A twoja struktura bazy danych? – Pipiks

+0

Dzięki za pomoc w tej sprawie! Edytowałem pytanie, aby uwzględnić zapytanie i strukturę bazy danych. – winston

+0

@freeman Dodałem sugerowane rozwiązanie kilka dni temu - rozwiązać problem lub nadal mieć problemy? – Yasir

Odpowiedz

3

słownika wyglądać następująco:

▿ 1 element 
    ▿ 0 : 2 elements 
    - key : "-KotqLUUucaRagTRt967" 
    ▿ value : 3 elements 
     ▿ 0 : 2 elements 
     - key : sender 
     - value : eGTYRSo81JefgasYLRHUFHUTnEC3 
     ▿ 1 : 2 elements 
     - key : text 
     - value : test 
     ▿ 2 : 2 elements 
     - key : timestamp 
     - value : 1499914135546 

Ale w rzeczywistości to powinno wyglądać (Jeśli chcesz uzyskać dostęp do słownika [ "nadawcę"]):

▿ 2 elements 
    ▿ 0 : 2 elements 
    - key : sender 
    - value : eGTYRSo81JefgasYLRHUFHUTnEC3 
    ▿ 1 : 2 elements 
    - key : text 
    - value : test 
    ▿ 2 : 2 elements 
    - key : timestamp 
    - value : 1499914135546 

Pierwsze rozwiązanie:

Musisz dodać .child ("- KotqLUUucaRagTRt967") w zapytaniu.

LUB

drugie rozwiązanie:

Trzeba zrobić coś takiego:

query.observe(.childAdded, with: { snapshot in 
    for child in snapshot.children { 
     guard let value = child.value as? NSDictionary else { 
      return 
     } 

     guard let sender = value["sender"] as? String else { 
      return 
     } 

     // You can user the sender 
    } 
}) 

UPDATE:

query.observe(.childAdded, with: { snapshot in 
    for child in snapshot.children.allObjects as! [FIRDataSnapshot] { 
     if let value = child.value as? [String:Any], let sender = value["sender"] as? String { 
      // You can user the sender 
     } 
    } 
}) 

UWAGA

Wymieniłem observeSingleEvent z obserwować, jak Frank van Puffelen powiedział, że jest to niczym niezwykłym połączeniem dla .childAdded.

+0

Dzięki! Pojawia się błąd "Wartość typu Dowolna nie ma wartości członka". Występują błędy na wartości "value = child.value". Jakieś pomysły? – winston

+0

@ freeman czy upewniłeś się, że włączasz 'guard let' przed wartością" value = child.value'? –

+0

@RajatKhare tak nadal błędy w tym wierszu 'guard let value = child.value as? NSDictionary else {return} '. XCode sugeruje zmianę go na 'guard let value = (child jako AnyObject) .value as? NSDictionary else {return} 'ale potem to powoduje błąd' Niejednoznaczne użycie wartości' – winston

4

Nie sądzę, że chcesz obsługi ChildAdded, więc idę z przykładem obserwować SealEvent, ponieważ chcesz zapytanie danych z bazy danych w tym czasie bez wyzwalaczy. Podczas korzystania z obiektuobserwSingleEvent ważne jest, aby baza danych była zsynchronizowana. Polecam za pomocą poniższego kodu:

query.keepSynched(true) //keeps data in sync with database, if you have data persistince on in your appDelegate 
query.observeSingleEvent(of: .value, with: { (snapshot) in //notice the changed here 
      print(snapshot) 
      //Since you want to loop again because there could be multiple 
      //messages in that chatroom which all have a unique ID, do this loop: 
      let enumerator = snapshot.children 
      while let rest = enumerator.nextObject() as? FIRDataSnapshot { 
       //this is 1 single message here 
       let values = rest.value as? NSDictionary 
       for (key, value) in values{ 
       print("Key: \(key), value: \(value)") 
       } 
       //lets say you want to check if there is a value with a key named "text": 
      let textUser = values?["text"] as? String ?? "No text found" 
       //providing a default value if there is no text. You could leave it empty, than it is nil (not recommend) 
       //Not only is this a lot more readable, I do not use force unwrapping so your app 
       //cannot cause an exception. 

       //Get more values from the dictionary as I did with textUser 
       //Initialize message than here. You will see you do not need to force unwrap anything :D 
       } 

      } 

     }) 
+0

"Ty i Pipiks łączycie obiekt obserwacyjny" Widzieć z dwójką "z dzieckiem dodanym, ta dwójka nie pasuje do siebie" Chociaż jest to niezbyt częste połączenie, nie ma techniczny powód, którego nie można łączyć. –

+0

Uzgodnione, nie rozumiem, dlaczego nie można połączyć jednego wydarzenia z dzieckiem dodanym? – Yasir

+0

@ Yasir Nie wiedziałem na pewno, to dlatego "Myślę, że!". Z dokumentów, które czytam, dziecko dodawane jest uruchamiane za każdym razem, gdy dodawane jest nowe dziecko. Funkcja noticeSingleEvent odczyta dane w takim stanie, w jakim się znajdują. Myślałem, że dwa nie będą działać razem, ale Frank już mnie poprawił, będę edytować tę część. –

3

Jak Pipiks wyjaśnił, Twój problem jest to, że próbujesz uzyskać dostęp do indywidualnych szczegółów wiadomości na jednym poziomie wyższym niż zwracanych danych.

Wartość migawki podaje słownik komunikatów czatu, w których kluczami najwyższego poziomu są klawisze wiadomości czatu. Aby mapować zwracanych danych do tablicy komunikatów, chciałbym użyć następującego kodu:

query.observeSingleEvent(of: .childAdded, with: { snapshot in 

    guard let messagesDict = snapshot.value as? [String: AnyObject] else { return } 

    self.messages = messagesDict.flatMap({ (messageId: String, messageData: Any) -> Message? in 
     guard 
      let sender = messageData["sender"] as? String, 
      let text = messageData["text"] as? String, 
      let timestamp = messageData["timestamp"] as? Int, 
      let message = Message(key: messageKey, sender: sender, text: text, timestamp: timestamp) else { 
       return nil 
     } 
     return message 
    }) 

    self.tableView.reloadData() 
}) 

Co to robi to na mapie słownika komunikatów do tablicy Message obiektów.

Użyłem flatMap do odfiltrowania wiadomości, które nie mają wartości nadawcy, tekstu lub datownika (więc flatMap zwraca obiekt [Message]).

Czy to rozwiązuje problem?

+0

Zostawiłem kod indexPaths, ponieważ nie wygląda na to, że jest używany wszędzie :) – Yasir