Firebase - iOS suddenly returning null for snapshots that I know exist? - ios

I came back to work on a project I have not touched in a week and suddenly my code was not working. I take a snapshot of data that I am sure exists (I can see it exactly in the database and changed no code) yet it is returning NSNULL for the snapshot and when I print snapshot.exists() I get false. I even tried printing snapshot.ref and typing that link into my browser and that takes me to the data on the console.
The only thing I did today was manually add a piece of data into my firebase console, but it was not in the same node where I am getting this error and it was working for a while after I made the change so I don't see how that could have caused this. Is anyone else having this issue or know why this would suddenly start happening?
Here is my code:
_ = ref.child("profiles").child((FIRAuth.auth()?.currentUser?.uid)!).child("type").observeSingleEventOfType(FIRDataEventType.Value, withBlock: { (snapshot) in
print(snapshot.exists())
print(snapshot.ref)
if (snapshot.value as! String == "Player") {
.....
}
})
I'm getting the error Could not cast value of type 'NSNull' (0x10d008600) to 'NSString' (0x10d3ffb48).' and as I said earlier snapshot.exists() is false and the ref link works.
Thanks!

Related

Firebase's snapshot.value cast to Bool suddenly returning nil

So my code was working perfectly fine but today it is returning nil when I try to cast Firebase's snapshot.value to a Bool. I haven't made any change to code at all. But it works fine if I cast it to a String (as? String returns "true").
Same issue at another place where I was casting to [String: Bool].
One thing that is different from earlier, I installed Xcode 10 beta 3 today (Xcode 9.4 is installed too). Both Xcode versions are returning nil. Here's the code:
if let currentUserId = Auth.auth().currentUser?.uid{
Database.database().reference().child("users/\(currentUserId)/share").observe(.childAdded) { (snapshot) in
let data = snapshot.value as? Bool
if data == true{
self.showNotificationsBadge()
}
}
}
Edit: Snapshot is not nil. You can see that in the console pane. I have printed both snapshot.key and .value.
Edit 2: I'm sorry if my question caused any confusions. The main purpose of this question is to know the problem, is it Firebase SDK or Xcode. Because it was working perfectly till now. I know how I can tackle this and how can I convert a String to a Bool.
Edit 3: Thank you everyone for your answers. I'm sorry I was unable to deliver my thoughts correctly. I just want to know about this unpredicted behavior and why is it happening? Who is the culprit here? Xcode, Firebase SDK? This code worked PERFECTLY FINE for about a month. I'm not asking for a solution, I'm just curious about this behavior. It would be great if someone from team Firebase can explain this issue.
Edit 4: Removed image and added code. Also figured out the issue thanks to #Jay's comment.
You need check if the snapshot is nil before checking the value.
if let data = snapshot.value as? Bool {
....
}
This happened to me just recently. I discovered that I had quotes around the child value, eg. "true". Remove the quotes and the solution from #Maximo should work as expected.

observeSingleEvent with queryEqual to value doesn't work

So, I want to check if user's device is in my list (for testing). For this I have a small set of values in my Firebase dataset.
It looks like that:
But when I'm trying to check if the user's id is in this list, I'm getting nothing.
let childString = "tempfreeuuid/"
let pointref = ref.child(childString)
let query = pointref.queryOrderedByKey().queryEqual(toValue: "FFFFF")
query.observeSingleEvent(of: DataEventType.value) { (snapshot) in
if snapshot.hasChildren() {
print("that's good")
} else {
print("snapshot has no children")
}
}
And the result is "snapshot has no children".
I've already tried query.observeSingleEvent(of: .childAdded) (doesn't work), .queryLimited(toFirst: 3), and .queryOrderedByKey() — these two don't work either.
At the same time this query is working if I'm not trying to use queryEqual.
What am I doing wrong?
update: I want to clarify the problem I have. I don't have any results, snapshot is null. At the same time if I'm using queryLimited(toFirst: 1) instead of queryEqual, I'm getting one result from the table to work with. It seems to me it's not about snapshot issues, it's about query without any results.
You are using the wrong OrderedBy method. Because you are using queryOrderedByKey the queryEqual function will check if its equal to the Key while you want to compare it to the Value.
Instead you should be using queryOrderedByChild or queryOrderedByValue to make sure you compare the right values.
Here is the reference to the firebase docs explaining how queries (specificly queryEqualToValue in your case) work.

iOS Firebase - Crash in simulator but not device w/ persistence

I tried googling this problem but it seems like everyone has the opposite problem where the app runs on simulator but not their device. I've been struggling a LOT all week with firebase asynchronous calls returning null and linked the issue to persistence being enabled. All my problems go away if I disable persistence, but I want it enabled. I learned recently about synchronous issues with the different listeners/persistence and have been struggling with firebase returning outdated/nil values for a while.
Simulator was working just a week or two ago and I'm not sure what's changed. I've tried messing with / switching out .observeSingleEvent for .observe and still crashes at this code:
let synced = ref.child("profiles").child((FIRAuth.auth()?.currentUser?.uid)!).child("level")
synced.observeSingleEvent(of: FIRDataEventType.value, with: { (snapshot) in
print(snapshot)
print(snapshot.ref)
if (snapshot.value as! String == "One") {
........//CRASH
With the message:
Could not cast value of type 'NSNull' (0x10b7cf8c8) to 'NSString' (0x10a9dfc40).
When I try to print snapshot, it shows me an empty snapshot. But when I print the ref, the link works and takes me to the right place in my db (where I can see the data exists)
Any ideas how to fix/get around this without disabling persistence? Or more importantly I guess, should I care that it doesn't work in simulator if it works on a device? Will this matter for app store approval / affect future users?
If you'd like to see for yourself that this is an issue of firebase getting a nil/outdated value when the reference exists, here is what I see when I follow the printed ref link
The error seems fairly explicit: there is no value, so you can't convert it to a string.
synced.observeSingleEvent(of: FIRDataEventType.value, with: { (snapshot) in
if (snapshot.exists()) {
if (snapshot.value as! String == "One") {
........//CRASH

Trouble retrieving data from Firebase using .Value/.Child added in swift

i am working on a project where I am pulling data from firebase (which is "queued"). Essentially data is being saved w/ a time stamp so when it's called, it can be ordered sequentially (first in, first out).
The problem I am facing is when I retrieve the data on my app. From my research, on Stack overflow as well as firebase docs, .Value gives a snapshot and continues to listen to data when new data is added. However when new data is added it will take a new snapshot of the entire set (hence "duplicating data" on my app's array).
To get around this I have tried to instead use .ChildAdded, which works well to add new data to my array when new data is added to the firebase database. However it isn't adding the full data set (data that is already existing in the database), which is what I need in addition to new data being added.
Suppose firebase nodes as such:
App_Queue:
Category1:
Timestamp1:
Uid: User_1_uid
Timestamp2:
Uid: User_2_uid
Swift code (2.3):
Case1:
self.databaseRef.child("App_Queue/\(Category1)").queryLimitedToLast(15).observeEventType(.Value, withBlock: { (snapshot) in
if let userDict = snapshot.value as? [String:AnyObject]{
for each in userDict{
let timeIdExtract = each.0 as! String
self.timeIdArray.append(timeIdExtract)
print(self.timeIdArray)
}
//this gives me full snapshot of time stamps & a userId
//but if timestamp3 and user_3_uid is added to firebase, the array is appended with a new snapshot thus, duplicating items.
Case2:
self.databaseRef.child("App_Queue/\(Category1)").queryLimitedToLast(15).observeEventType(FIRDataEventType.ChildAdded, withBlock: { (snapshot : FIRDataSnapshot) in
if let userDict = snapshot.value as? [String:AnyObject]{
for each in userDict{
let timeIdExtract = each.0 as! String // Every follwers ID.
self.timeIdArray.append(timeIdExtract)
print(self.timeIdArray)
}
//this gives me only new items added, but not already added.
// if timestamp3 and user_3_uid is added the array is appended with this new item. But timestamp1 & timestamp2 not added
Case 3:
I have tried a hybrid of Case1 (instead use .observeSingleEventOfType()) & Case2, by adding a self.databaseRef.removeAllObservers() after the code in case 1, and then turning on the .ChildAdded observer for case2. It almost works.... added initial snapshot via case 1, then listens however if say, timestamp2 is recently added it will append this again when Case2 is called, thus duplicating the array.
So my question: how the heck do I go about getting existing objects in the database AND adding on new ones, without duplicating data in the array?
EDIT
Im silly-- had some extraneous code after the block which was throwing things off. DOH! For anyone experiencing issues, first place to check! also .ChildAdded paired with observeEventType did the trick. (takes all previous data already in DB + adds new data as it comes in).
self.databaseRef.child("App_Queue/\(Category1)").queryLimitedToLast(15).observeEventType(.ChildAdded, withBlock: { (snapshot) in
...
Im silly-- had some extraneous code after the block which was throwing things off. DOH! For anyone experiencing issues, first place to check! also .ChildAdded paired with observeEventType did the trick. (takes all previous data already in DB + adds new data as it comes in).
self.databaseRef.child("App_Queue/\(Category1)").queryLimitedToLast(15).observeEventType(.ChildAdded, withBlock: { (snapshot) in
...

Parse with Swift - User Queries

Im trying to query my Parse User database in order to create a friend request between two users. The user inputs a user name that they want to add as a friend. However, when I try to query the database, I get a "EXC_BAD_ACCESS" error on the line where I am adding the condition. Not sure why Im getting this error, as its my understanding it has to do with trying to access memory already freed. Anything that you can do to help would be very appreciated!
var friendship = PFObject(className: "Friends")
var findUser:PFQuery = PFUser.query()
findUser.whereKey("username",equalTo:username2) //program crashes here for some reason
findUser.getFirstObjectInBackgroundWithBlock {
(user2, error: NSError!) -> Void in
if user2 == nil {
println("Failure")
} else {
println("Successfully retrieved the object.")
friendship["user1"] = PFUser.currentUser().objectId
friendship["user2"] = user2.objectId
friendship["pending"] = true
friendship.save()
}
}
Set a breakpoint in the compiler and navigate the steps until you hit the crash so you can understand exactly at which point it crashes a troubleshoot further from there with the better understanding.
Also once it has crashed use LLDB print out po ivar to check if any of your ivars got instantiated and which ones are empty or execute dubious functions with exp func.
So... It works today. Not sure what happened. Co-Developer and I reorganized frameworks and everything works fine now. Thank you for your help everyone. I appreciate the responses :)

Resources