Load Specific data from JSON with Random Values Swift - swift

I am using firebase and I am trying to retrieve data from Firebase Database which is working well however when I call "postDict" I get.
["-KPZAOg58kUdqwYMzlDJ":
{
description = jpeg;
listingImageURL = "https://firebasestorage.googleapis.com/v0/b/hype-central.appspot.com/o/lidsafstings%2FC73FdfB8A0-968df7-44DB-B96B-A10DC1E3A2B7.png?alt=media&token=b6e296f2-8854-4b76-9bfc-470dfd69d11f2f";
location = jpeg;
price = 54;
title = jpeg;
userDisplayName = "Brandon YOIO";
userid = pRuwvL7WyzQpY0G22ZLYCmTTemB3;
},
"-KPZ0yLhcfLvP9YWNjbC": {
description = "Description ofvaroe";
listingImageURL = "https://firebadfasestorage.googleapis.com/v0/b/hype-central.appspot.com/o/listings%2F0ACdasfCD645-2E2C-4936-B3DF-37EC55AA0157.png?alt=media&token=b321dasff42f-75b5-4eb3-b129-b0a902cc5926";
location = Vancouver;
price = 34;
title = eclipse;
userDisplayName = "Brandon YOIO";
userid = pRuwvL7WyzQpY0G22ZLYCmTTemB3;
},
"-KPoCsNS63JZdbTJIdaP": {
description = Brandon;
listingImageURL = "https://firebadasfsestorage.googleapis.com/v0/b/hype-central.appspot.com/o/listings%2FOptional(%22pRuwvL7WyzQpY0G22ZLYCmTTemB3%22)%2F3EACE28E-D28A-464A-B6D0-FB502E9dafsB4775.jpeg?alt=media&token=1d45bc7b-7273-4d33-8ccd-755f3102a23c";
location = BRANDON;
price = BRANDON;
title = BRANDON;
userDisplayName = "Brandon YOIO";
userid = pRuwvL7WyzQpY0G22ZLYCmTTemB3;
},
"-KP_Y7ug7hwrHtW6VNqV": {
description = "Description ofvaroe";
listingImageURL = "https://firebaseddasfstorage.googleapis.com/v0/b/hype-central.appspot.com/o/listings%2FC5daf7991BA-D7E0-4C8A-96E7-0DB17EEBABD7.jpeg?alt=media&token=efd03b4d-6964-4685-9b48-5ed36a4ceb59";
location = "";
price = "";
title = "";
userDisplayName = "Brandon Mayhew";
userid = pRuwvL7WyzQpY0G22ZLYCmTTemB3;
}]
If I call "postDict["-KPZAOg58kUdqwYMzlDJ"]["title"]" It will print the title which is exactly what I want however how do I get an array of all the titles in this JSON format (not just the title of "-KPZAOg58kUdqwYMzlDJ").
How do I get all the title's?

Use :-
rootRef.observeEventType(.Value, withBlock: {(postDictionary) in
if let postDict = postDictionary.value as? [String:AnyObject]{
for each in postDict as [String:AnyObject]{
let autoID = each.0
rootRef.child(autoID).observeEventType(.Value, withBlock: {(specificPost) in
//RETRIEVE YOUR DATA
})
}
}
})
PS:- I have used rootRef as you have not specified your parent nodes in your JSON structure :)

Related

How to add variables from a firebase snapshot

I know this question has been ask several times but none of the solutions work for me. here is my snap shot
Snap (CaseExtend) {
NYxdSlq8yOgQd3phssRlD = {
CaseMinute = {
WMKuImjuH0qPIGJhHHJKv = {
caseMinute = "";
dateTime = "Dec 1, 2021 12:20 PM";
minuteId = WMKuImjuH0qPIGJhHHJKv;
userId = OtRFaqilTigWvEkUCASvCoEegny1;
};
};
CaseParticipant = {
3f7nqmcWFTenePkEB9KoMHLzVtk2 = {
userId = 3f7nqmcWFTenePkEB9KoMHLzVtk2;
};
OtRFaqilTigWvEkUCASvCoEegny1 = {
userId = OtRFaqilTigWvEkUCASvCoEegny1;
};
};
caseId = Oj7TwzDC3HQMJKyTb8Ebi;
caseNumber = TEST;
court = "Labour Tribunal";
courtRoomNo = "";
date = "2021-12-01";
extendId = NYxdSlq8yOgQd3phssRlD;
extendStatus = "Not Extend";
location = "";
participantCount = 2;
profilePicture = "https://firebasestorage.googleapis.com/v0/b/lege-155e1.appspot.com/o/Profile%20Pictures%2FOtRFaqilTigWvEkUCASvCoEegny1.jpg?alt=media&token=676226fa-638b-4175-a8d5-247095f6b86a";
step = TBM;
time = "";
userId = OtRFaqilTigWvEkUCASvCoEegny1;
};
}
and i retrieve the snapshot using following code,
ref.child("CaseExtend").queryOrdered(byChild: "userId").queryEqual(toValue: "OtRFaqilTigWvEkUCASvCoEegny1" ).observe(.value, with: { (DataSnapshot) in
})
i want to add the caseID, caseNumber, date.. and other values for different variables. is there anyway i can do this?
first of all you are getting all data in casetExtend node all the variables you want to assign is not under that node. for that you need to navigate one level of child node.
ref.child("CaseExtend").queryOrdered(byChild: "userId").queryEqual(toValue: "OtRFaqilTigWvEkUCASvCoEegny1" ).observe(.value, with: { (snapshot) in
for caseSnapshot in snapshot.children.allObjects as! [DataSnapshot] {
let dict = caseSnapshot.value as? [String: AnyObject] // assign the snapshot to a dictionary
let court = dict!["court"] as? String ?? "unknown"; // assign the variable
}
})

Remove All Items from NSDictionary/Dictionary where value == -1.0

I am migrating my data from 1 format to another for a large update to one of my iOS apps. This means that when a user updates their application it migrates their data to a new location. This new location has much stricter rules and uses proper practices (basically when I first created the app I was a noob and there are bad practices currently in the database and this new location is for good data only).
I have everything migrating nicely and everything works except I need to do one last thing. The large dictionary that I save to the database (it uses firebase fyi) has -1.0 stored everywhere there should be a nil value (bad, I know). What I need to do is loop through the entire dictionary and remove any key where the value of that key is -1.0.
The Dictionary is of type [AnyHashable : Any] which is what firebase uses.
I have tried this so far.
if let data = dataDictionary as? [AnyHashable : Any] {
let foundItems = data.filter { $0.value as? Double == -1.0 }
print(foundItems)
}
the plan was to then loop through that found items array and remove any key from the data dictionary that contained it.
This is what the data dictionary looks like:
"-KpIdh_TQMG4fyfFgkdt" = {
assignments = {
"-KpIgH6uN19OpcuedYe1" = {
assignmentGoal = "-1";
assignmentName = "Information System Proposal";
assignmentResult = 100;
assignmentWeight = 5;
};
"-KpIgJnFlC6fhgS0NWxF" = {
assignmentGoal = "-1";
assignmentName = "Information System";
assignmentResult = "-1";
assignmentWeight = 35;
};
"-KpIgOGSAwg_VSpDWhWR" = {
assignmentGoal = "-1";
assignmentName = "Process Analysis";
assignmentResult = "-1";
assignmentWeight = 30;
};
"-KpIgPhu_3Zxw36xt3O4" = {
assignmentGoal = "-1";
assignmentName = Labs;
assignmentResult = "-1";
assignmentWeight = 10;
};
"-KpIgQoFEdRnLlMAq2VN" = {
assignmentGoal = "-1";
assignmentName = Exam;
assignmentResult = "-1";
assignmentWeight = 20;
};
};
paperColor = 22;
paperGoal = 95;
paperName = "Systems Analysis";
};
};
semesterCode = 17S2;
semesterGoal = 90;
semesterName = "2017 Semester Two";
};
};
and this is what it should look like
"-KpIdh_TQMG4fyfFgkdt" = {
assignments = {
"-KpIgH6uN19OpcuedYe1" = {
assignmentName = "Information System Proposal";
assignmentResult = 100;
assignmentWeight = 5;
};
"-KpIgJnFlC6fhgS0NWxF" = {
assignmentName = "Information System";
assignmentWeight = 35;
};
"-KpIgOGSAwg_VSpDWhWR" = {
assignmentName = "Process Analysis";
assignmentWeight = 30;
};
"-KpIgPhu_3Zxw36xt3O4" = {
assignmentName = Labs;
assignmentWeight = 10;
};
"-KpIgQoFEdRnLlMAq2VN" = {
assignmentName = Exam;
assignmentWeight = 20;
};
};
paperColor = 22;
paperGoal = 95;
paperName = "Systems Analysis";
};
};
semesterCode = 17S2;
semesterGoal = 90;
semesterName = "2017 Semester Two";
};
};
The solution I have is to map (iterate) over each parent key and assign it's child nodes to a variable child. Then test each child property (assignmentGoal, assignmentName etc) for either "-1" for the string and -1 for the ints. If it's a match, remove that key: value pair from child.
Then assign child back to the parent node.
let result: [Any] = dict.map { dictionary in
var d = dictionary
var child = d.value as Dictionary
if let goal = child["assignmentGoal"] as? String, goal == "-1" {
child.removeValue(forKey: "assignmentGoal")
}
if let name = child["assignmentName"] as? String, name == "-1" {
child.removeValue(forKey: "assignmentName")
}
if let result = child["assignmentResult"] as? Int, result == -1 {
child.removeValue(forKey: "assignmentResult")
}
if let weight = child["assignmentWeight"] as? Int, weight == -1 {
child.removeValue(forKey: "assignmentWeight")
}
d.value = child
return d
}
//show the output
for item in result {
print(item)
}
and the result output
(key: "-KpIgOGSAwg_VSpDWhWR",
value: ["assignmentName": "Process Analysis System", "assignmentWeight": 30])
(key: "-KpIgQoFEdRnLlMAq2VN",
value: ["assignmentName": "Exam", "assignmentWeight": 20])
(key: "-KpIgJnFlC6fhgS0NWxF",
value: ["assignmentName": "Information System", "assignmentGoal": "3", "assignmentWeight": 35])
(key: "-KpIgPhu_3Zxw36xt3O4",
value: ["assignmentName": "Labs", "assignmentWeight": 10])
(key: "-KpIgH6uN19OpcuedYe1",
value: ["assignmentName": "Information System Proposal", "assignmentResult": 100, "assignmentWeight": 5])

Firebase getting data in order

I am using Firebase and I have had no problems getting data in alphabetical order until recently. I never used queries, I always just used snapshots of data and sorted through them one-by-one. Recently, the data has not been always coming in alphabetical order in the snapVal. How do I make it so I get a snapVal of data sorted alphabetically, like it is in the snapshot from the database?
Real Example: there are 4 messages, id1-id4 (in that order). They contiain the message "1"-"4". The snapshot comes looking correct. But the snapVal (snapshot.value) looks like this:
["id2": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 2;
TIME = "8:12 PM";
}, "id4": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 4;
TIME = "8:12 PM";
}, "id1": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 1;
TIME = "8:12 PM";
}, "id3": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 3;
TIME = "8:12 PM";
}]
What the snapshot looks like:
["id1": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 1;
TIME = "8:12 PM";
}, "id2": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 2;
TIME = "8:12 PM";
}, "id3": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 3;
TIME = "8:12 PM";
}, "id4": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 4;
TIME = "8:12 PM";
}]
To get the snapVal, I use this:
if let snapVal = snapshot.value as? [String: AnyObject] {
// Comes out of order..
}
To clarify:
Snapshot (this ends up coming out correct):
Snap (CHAT) {
id1 = {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 1;
TIME = "8:12 PM";
};
id2 = {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 2;
TIME = "8:12 PM";
};
id3 = {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 3;
TIME = "8:12 PM";
};
id4 = {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 4;
TIME = "8:12 PM";
};
}
This is the output for print(snapVal.keys) inside if let snapVal = snapshot.value as? [String: AnyObject]:
LazyMapCollection<Dictionary<String, AnyObject>, String>(_base: ["id2": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 2;
TIME = "8:12 PM";
}, "id4": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 4;
TIME = "8:12 PM";
}, "id1": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 1;
TIME = "8:12 PM";
}, "id3": {
DATE = "10/20/16";
"FIRST_NAME" = first;
ID = userID;
"LAST_NAME" = last;
MESSAGE = 3;
TIME = "8:12 PM";
}], _transform: (Function))
My Code:
self.firebase.child("Chats").child(chatID).queryOrderedByKey().observeSingleEvent(of: .value, with: { (snapshot) in
print(snapshot)
if let snapVal = snapshot.value as? [String: AnyObject] {
print(snapVal)
for c in snapVal {
print("checking Message as child")
let message = c.value["MESSAGE"] as? String
let fn = c.value["FIRST_NAME"] as? String
let ln = c.value["LAST_NAME"] as? String
let USER_ID = c.value["ID"] as? String
if let userID = USER_ID {
if let msg = message {
if let firstName = fn {
if let lastName = ln {
let username = "\(firstName) \(lastName)"
self.addMessage(userID, text: msg, name: username)
print("Message added! \nMessage Info:")
print("User ID: \(userID)")
print("text: \(msg)")
print("Username: \(username)")
} else {
print("LN did not pass")
}
} else {
print("FN did not pass")
}
} else {
print("Msg did not pass")
}
} else {
print("User ID did not pass")
}
}
}
})
Since you haven't shared the necessary code, I'll assume you're doing something along these lines:
ref!.queryOrdered(byChild: "text").observe(.value, with: { (snapshot) in
print("\(snapshot.value)")
})
When you execute a query on a Firebase location, the data is returned with information about the order of the items according to the query. When you observe a value event, the snapshot contains the keys, the values and the order of the children.
But when you convert request the snapshot.value property, all information has to be converted into a dictionary. The keys and the values of each child survive this conversion, but the information on ordering is lost.
For this reason, you'll have to use the children property of the snapshot to iterate over the children in the correct order:
ref!.queryOrdered(byChild: "text").observe(.value, with: { snapshot in
for child in snapshot.children {
print("child \(child)")
}
})
Solution: After very extensive searching and attempting, the problem still persisted that once the snapshot was converted to a snapVal (snapshot.value), the order often rearranged. My (working) solution:
for child in snapshot.children {
let child = child as! FIRDataSnapshot
if let childVal = child.value as? [String: AnyObject] {
let childMessage = childVal["MESSAGE"] as! String
// more code for each child. This child might be a post of a sort, which you can access properties of in a way like I did in the line above
}
}
Process:
Loop through each child in snapshot
Convert the child to a FIRDataSnapshot so it is not an element
Get the value of the particular child to access properties from
Add in the respective code for the child following NSDictionary principles.
Why this solution is solid
Receiving snapshots in the proper order is very simple. The issue I faced was getting data in the correct order when I got the snapshot.value. This solution fixes that because the values of each child are only accessed when looping through the children of snapshot, which is sorted. This leaves the order of children still in the control of the snapshot.
I also like the snapshot.value approach by using [String: AnyObject] because it is very close to the old functionality of Firebase implementation in Swift: Simple and very clean. I actually think that using NSDictionary in this way is really a way to save time in the long run because it is not verbose in any way.
From my experience with Firebase you cannot guarantee the order that the data is being returned in the snapshot value. Firebase provides a couple of functions that you can add to your reference query though to order and sort the data based on key queryOrderedByKey, value queryOrderedByValue, or child queryOrderedByChild.
From your description it sounds like you may want to use queryOrderedByChild to sort you snapshots correctly.
Here's the documentation on those functions and scroll down to the sort data section. https://firebase.google.com/docs/database/ios/lists-of-data
The problem as you can see is not that Firebase is not giving you the response ordered by as requested, the problem is that you are parsing the response into an Dictionary and Dictionaries are no ordered list. The simplest way to fix it is to order your dictionary using something like this:
self.messages.sortInPlace({ ($0.date.compare($1.date) == NSComparisonResult.OrderedAscending)})
Or a even better way is to add the result directly into an array.
You can find more about this problem in this question in my course, there is a long discussion about it there (https://www.udemy.com/firebase/learn/v4/questions/1341056).
Let me know if that helps you.

Swift accessing key from dictionary returning null

I have a dictionary. When I try to access that dictionary, it is returning a null value when it should definately be returning an actual value. I'm stumped. Any help is always appreciated.
if let d = response.result.value {
print(d) //prints correct data
let prices = d["prices"] as? [[String:AnyObject?]]
print(prices) //prints nil
let best_price = prices?[0]
let price = best_price?["price"] as? String
print(price) //prints nil
}
Console:
{
item = {
"item_number" = 57;
image = "http://example.com/tent.jpg";
name = "Small Red Tent";
};
prices = (
{
link = "http://example.com/id=19";
price = "58.15";
rating = "3.64";
"vendor_id" = 50;
},
{
link = "http://example.com/id=50";
price = "58.14";
rating = "5.00";
"vendor_id" = 110;
},
{
link = "http://example.com/id=26";
price = "50.40";
rating = "4.71";
"vendor_id" = 73;
},
{
link = "http://example.com/id=12";
price = "47.16";
rating = "4.00";
"vendor_id" = 1;
},
{
link = "http://example.com/id=13";
price = "45.75";
rating = "3.90";
"vendor_id" = 25;
},
{
link = "http://example.com/id=16";
price = "41.32";
rating = "3.02";
"vendor_id" = 16;
},
{
link = "http://example.com/id=1";
price = "36.59";
rating = "4.84";
"vendor_id" = 51;
},
{
link = "http://example.com/id=2";
price = "36.29";
rating = "3.26";
"vendor_id" = 43;
},
{
link = "http://example.com/id=13";
price = "34.59";
rating = "4.14";
"vendor_id" = 48;
},
{
link = "http://example.com/id=3";
price = "32.00";
rating = "4.29";
"vendor_id" = 53;
},
{
link = "http://example.com/id=4";
price = "24.50";
rating = "4.16";
"vendor_id" = 8;
},
{
link = "http://example.com/id=5";
price = "15.00";
rating = "4.87";
"vendor_id" = 39;
},
{
link = "http://example.com/id=6";
price = "0.00";
rating = "3.00";
"vendor_id" = 65;
}
);
}
nil
nil
So the solution was proposed by Larme solved the problem.
let prices = d["prices"] as? [AnyObject]
Although I never figured out why casting d["prices"] as? [[String:AnyObject?]] wouldn't also work.

how to parse this in iphone

{
education = (
{
school = {
id = 108102169223234;
name = psss;
};
type = College;
year = {
id = 142833822398097;
name = 2010;
};
}
);
email = "amvijaycse#gmail.com";
"first_name" = Vijay;
gender = male;
id = 100000782204693;
"last_name" = Kumar;
link = "http://www.facebook.com/profile.php?id=100000782204693";
locale = "en_US";
location = {
id = 106377336067638;
name = "Bangalore, India";
};
name = "Vijay Kumar";
timezone = "5.5";
"updated_time" = "2010-11-21T07:45:11+0000";
}
i needed email,firstname,lastname.
[EDIT: Removed because it was inaccurate]