问题
Hello I'm new at swift programming and i want to get label
value from loadData()
to use use for my path (reference) to my database on dbRef!.child(place+"/placeLabel")
. What I mean?! I read data that are on "Dio Con Dio" node. That happens because the value place
is let place = "Dio Con Dio"
. So, my application doesn't load data from "Paradosiako - Panorama" node. I want to load everything from database and i thought that if i could make place
value to change to the next node, it could read all the data.
import UIKit
import FirebaseDatabase
class PlacesTableViewController: UITableViewController {
//MARK: Properties
@IBOutlet weak var placesTableView: UITableView!
//database reference
var dbRef:FIRDatabaseReference?
var places = [Places]()
private var loadedLabels = [String: String]()
private var loadedRatings = [String: Int]()
//handler
var handle:FIRDatabaseHandle?
override func viewDidLoad() {
super.viewDidLoad()
dbRef = FIRDatabase.database().reference()
// Loads data to cell.
loadData()
}
private func loadData() {
let place = "Dio Con Dio"
dbRef!.child(place+"/placeLabel").observe(.childAdded, with: {
(snapshot) in
let label = snapshot.value as! String
self.updatePlace(snapshot.key, label: label)
})
dbRef!.child(place+"/rating").observe(.childAdded, with: {
(snapshot) in
let rating = snapshot.value as! Int
self.updatePlace(snapshot.key, rating: rating)
})
}
private func updatePlace(_ key: String, label: String? = nil, rating: Int? = nil) {
if let label = label {
loadedLabels[key] = label
}
if let rating = rating {
loadedRatings[key] = rating
}
guard let label = loadedLabels[key], let rating = loadedRatings[key] else {
return
}
if let place = Places(name: label, rating: rating) {
places.append(place)
placesTableView.reloadData()
}
}
}
(This question is a follow up from this one.)
回答1:
For your new database schema, try this instead:
private func loadData() {
dbRef!.observe(.childAdded) {
(placeSnapshot) in
print("Adding place \(placeSnapshot.key)...")
// Load each label on the "placeLabel" list.
let labels = placeSnapshot.childSnapshot(forPath: "placeLabel")
for (key, label) in labels.value as! [String: String] {
self.updatePlace(key, label: label)
}
// Load each rating in the "rating" list.
let ratings = placeSnapshot.childSnapshot(forPath: "rating")
for (key, rating) in ratings.value as! [String: Int] {
self.updatePlace(key, rating: rating)
}
}
}
The updatePlace
function simply groups the label and rating properties, of a given place, that were separately loaded by loadData
.
Places removal. Of course, the above code won't handle place removal. To do so, you will need to listen for the childRemoved
event as well.
回答2:
It's difficult to explain this in a comment, so I'll address your current issue here, but Paulo answered your question, I believe. You could even open a new question on this issue.
Here's the code you're having an issue with:
for (key, rating) in ratings.value as! [String: Int] {
self.updatePlace(key, rating: rating)
}
There's nothing wrong with this code, as long as ratings.value is filled with string: integer pairs. Your error occurs because somehow a there is a key missing. (the runtime found a NSNull, so it couldn't convert the data to a dictionary)
You need to set a breakpoint where you are constructing the array in:
placeSnapshot.childSnapshot(forPath: "rating")
(which is called ratings here/locally). If is ok to ignore entries with no key, then skip them and don't append them to your array. But it's more likely you have an error and need to find out why you're adding a null value...
Does that make more sense? Please accept Paulo's answer if he solved an issue, and open a new question with more information about childSnapshot (the code), and someone will be sure help you. (I know I'll try.)
来源:https://stackoverflow.com/questions/43959004/getting-a-let-value-outside-a-function