Reputation: 4166
I don't have a storyboard. I'm doing everything programmatically.
The loadData()
method takes Firebase data, put it into a Company
object, and loads the object into the companies
array. In the didFinishLaunchingWithOptions
method in the App Delegate, I instantiated the class and called loadData()
When I run breakpoint at the line indicated by the comment and type "po companies" in the console, I get 0 companies. The print statements inside .observe
are printed to the console and I can see that the company's properties are non-null, but anything outside .observe
, including the for loop and the print statement called after the load data method in the App Delegate are not printed.
class informationStateController {
func loadData() {
//Set firebase database reference
ref = FIRDatabase.database().reference()
//Retrieve posts and listen for changes
databaseHandle = ref?.child("companies").observe(.childAdded, with: { (snapshot) in
//Code that executes when child is added
let company = Company()
company.name = snapshot.childSnapshot(forPath: "name").value as! String
print(company.name)
company.location = snapshot.childSnapshot(forPath: "location").value as! String
print(company.location)
self.companies.append(company)
print("databaseHandle was called")
})
for company in companies {
print(company)
}
//breakpoint inserted here
}
}
Why is my array empty and why are print statements outside .observe
NOT printing to the console? The output for the console is set to "All Output". I called import FirebaseDatabase
in the class and import Firebase
in the App Delegate.
Upvotes: 1
Views: 1226
Reputation: 72825
Per the docs (emphasis mine)
Important: The FIRDataEventTypeValue event is fired every time data is changed at the specified database reference, including changes to children. To limit the size of your snapshots, attach only at the highest level needed for watching changes. For example, attaching a listener to the root of your database is not recommended.
In your case, you're observing changes to the database, but no changes are happening, so you won't bet getting new data. I think the docs make this unnecessarily confusing, if you want to pull records that already exist, you have to query for it:
https://firebase.google.com/docs/database/ios/lists-of-data#sort_data
// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
let recentPostsQuery = (ref?.child("companies").queryLimited(toFirst: 100))!
Once you have that queried data, you can then deal with the observer and append data as required when new data is pushed.
All of this aside, Frank's answer is the reason you'll never see the print when a company is added even if you set the listener up right — you need to write that inside the completion block of the observer or query.
Upvotes: 0
Reputation: 598603
Data is loaded from the Firebase Database asynchronously. This means that by the time you print the companies, they won't have loaded yet.
You can easily see this by also printing the companies as they're loaded:
//Set firebase database reference
ref = FIRDatabase.database().reference()
//Retrieve posts and listen for changes
databaseHandle = ref?.child("companies").observe(.childAdded, with: { (snapshot) in
//Code that executes when child is added
let company = Company()
company.name = snapshot.childSnapshot(forPath: "name").value as! String
print(company.name)
company.location = snapshot.childSnapshot(forPath: "location").value as! String
print(company.location)
self.companies.append(company)
print("databaseHandle was called")
for company in companies {
print(company)
}
})
Now you'll first see one company printed (when childAdded
fires for the first time), then two companies (when childAdded
fires again), then three companies, etc.
Upvotes: 2