I'm using firebase to collect data, and i'm trying to retrieve the data in a usable format for an iPhone app, and i can't quite get it out properly. I'm writing the app in Swift.
The data is grouped by a date string then the with a random key and then the data. Eg:
{
"20160304" : {
"-KC-aOwSWpt4dlYmjJE4" : {
"coordinates" : "-37.7811465912404, 145.005993055861",
"event" : "Test event",
"time" : "2016-03-04 07:48:43 +0000"
}, etc...
I'm so far grabbing the data like this:
ref.queryOrderedByKey().observeEventType(.ChildAdded, withBlock: {
snapshot in
//print(snapshot.key) // date
print(snapshot.value)
})
And it returns something like this to the console:
{
"-KD8O0gL7gDGu_hRyFzQ" = {
coordinates = "-37.7540958861003, 145.001224694195";
event = "Test event";
time = "2016-03-18 11:02:32 +0000";
}; etc...
Does anyone know how i can get down to the next level, past the random keys, to the meaningful data? I had trouble before with this for javascript, but it's confusing me using swift.
I'd like to be able to grab the detailed data (bottom level) for a defined date (top level).
Try this code
let jsonLocations = snapshot.valueInExportFormat() as! NSDictionary
let keys = jsonLocations.allKeys
for key in keys {
let json = jsonLocations[key] as! [String: AnyObject]
self.sections.append(Location(JSONObject: json))
}
I usually try to stick to methods of FDatasnapshot as long as possible, which leads to:
ref.queryOrderedByKey().observeEventType(.ChildAdded, withBlock: { snapshot in
for child in snapshot.children {
print(child.key); // -KC-aOwSWpt4dlYmjJE4
print(child.childSnapshotForPath("event").value)
}
});
Related
I'm new to Swift, and coding in general, and have been working on a project where I'd like to create a UICollectionView populated with images from Firebase.
Each section of the UICollectionView would be a category, and each category would contain images related to that category. Each UICollectionView belongs to a parent, and I need to keep track of which parent has which categories, and which images are in each category.
To track the parents, categories, and images, I've set up the Firebase database in the following way (with bowl being the parent, the names of fruit as categories, and the keys are references to image data stored elsewhere in the database):
"bowl" : {
"apple" : {
"-LOM1R4EH9nszjJp0Va5" : true,
"-LOM1aRZT2XCE-6fvLBK" : true,
"-LOM1hSTmRY6wGrWMvIo" : true,
"-LOM1xnvKE6lc7fizomh" : true
},
"banana" : {
"-LOLmQWLXXyiCUwDBwID" : true
},
"pear" : {
"-LOLHakW-EtqevCeHfzl" : true,
"-LOM2DBGGuX5VQLmBz46" : true
},
"orange" : {
"-LOM26_pm6lbJ1D6hVPB" : true
}
}
The image data section of the database looks as follows:
"image" : {
"fruit" : {
"-LOLHakW-EtqevCeHfzl" : {
"description" : "round orange",
"imageURL" : "https://firebasestorage.googleapis.com/1/image1"
},
"-LOLmQWLXXyiCUwDBwID" : {
"description" : "big banana",
"imageURL" : "https://firebasestorage.googleapis.com/1/image2"
},
"-LOM1R4EH9nszjJp0Va5" : {
"description" : "small apple",
"imageURL" : "https://firebasestorage.googleapis.com/1/image3"
}
}
}
The approach I have been attempting to take is to create a dictionary with the image keys in it, then iterate through the image keys to grab the image data associated with each key (such as the imageURL), and then use the imageURL to download the images and populate the UICollectionView.
I've created a struct, as follows to transform the image data:
struct FruitPicture {
let imageURL: String
let description: String
init(imageURL: String, description: String) {
self.imageURL = imageURL
self.description = description
}
init?(snapshot: DataSnapshot) {
guard
let value = snapshot.value as? [String: AnyObject],
let imageURL = value["imageURL"] as? String,
let description = value["description"] as? String else {
return nil
}
self.imageURL = imageURL
self.description = description
}
func toAnyObject() -> Any {
return [
"imageURL": imageURL,
"description": description
]
}
}
I've been able to gather the imageURLs and populate a UICollectionView but it doesn't include the category details, and so far has involved a lot of manipulation of the data via snapshots, dictionaries, arrays, arrays of dictionaries, and so on, from one configuration to another and back again, and I've now become stuck and confused.
I've started looking at using multiple structs and nesting one within the other, like so, but I'm muddled on it all and am spending hours getting nowhere:
struct Picture {
var url: URL
var image: UIImage?
}
struct PictureCategory {
var name: String
var pictures: [Picture]
}
I was hoping for some advice, or roadmap, or details of how you would approach this, or some sample code, or anything to point me in the right direction. Thanks.
Edit to add more info
Thank you Iraniya your reply was very helpful and helped me consider things in a different way, I really appreciate it.
Taking your advice I've written the following which looks up a bowling creates a snapshot of the image meta data within (e.g the fruit and keys associated with that fruit) then uses those keys to create a snapshot of the image data (e.g key, imageURL, description). I then transform both snapshots into dictionaries, and return the dictionaries to the method which called it:
// GET DATA
static func getPicData(forKey bowlKey: String, completion: #escaping ([String : [Any]], [String : [FruitPicture]]) -> Void) {
var imageMetaDict: [String : [Any]] = [:]
var imageDataDict: [String : [FruitPicture]] = [:]
// DEFINE DATABASE TARGET
let ref = Database.database().reference().child("meta").child("bowl").child(bowlKey).child("fruit")
// GET DATA INTO SNAPSHOT AND TRANSFORM INTO DICTIONARY
ref.observeSingleEvent(of: .value, with: { (snapshot) in
guard let dict = snapshot.value as? [String:[String:Any]] else {
return completion([:],[:])
}
// DEFINE DISPATCH GROUP
let dispatchGroup = DispatchGroup()
// ITERATAE THROUGH DICTIONARY
for (categoryObject, fruitData) in dict {
// CREATE ARRAY TO STORE ITEMS
var itemArray = [String]()
// ITERATE THROUGH ITEMS IN FRUIT DATA
for item in fruitData {
// APPEND ITEM.KEY TO ITEM ARRAY
itemArray.append(item.key)
// ENTER DISPATCH GROUP
dispatchGroup.enter()
// USE ITEM.KEY TO GATHER IMAGE DATA
Service.viewPicData(forKey: item.key) { (fruitItem) in
if let fruitItem = fruitItem {
imageDataDict[item.key] = [fruitItem]
}
// EXIT DISPATCH GROUP
dispatchGroup.leave()
}
}
// STORE ARRAY IN DICTIONARY UNDER FRUIT CATEGORY KEY
imageMetaDict[categoryObject] = itemArray
}
// RETURN COMPLETION
dispatchGroup.notify(queue: .main, execute: {
completion(imageMetaDict, imageDataDict)
})
})
}
Each dictionary looks similar to the following:
imageMetaDict
[
"apple": ["-LOM1R4EH9nszjJp0Va5", "-LOM1xnvKE6lc7fizomh", "-LOM1hSTmRY6wGrWMvIo", "-LOM1aRZT2XCE-6fvLBK"],
"pear": ["-LOLHakW-EtqevCeHfzl", "-LOM2DBGGuX5VQLmBz46"],
"banana": ["-LOLmQWLXXyiCUwDBwID"],
"orange": ["-LOM26_pm6lbJ1D6hVPB"]
]
imageDataDict
[
"-LOM26_pm6lbJ1D6hVPB": [myApp.FruitPicture(imageURL: "https://firebasestorage.googleapis.com/1/image1", description: "pear 1")],
"-LOM2DBGGuX5VQLmBz46": [myApp.FruitPicture(imageURL: "https://firebasestorage.googleapis.com/1/image2", description: "banana 1")],
"-LOLmQWLXXyiCUwDBwID": [myApp.FruitPicture(imageURL: "https://firebasestorage.googleapis.com/1/image3", description: "apple 1")]
]
Is this on the right track with what you were suggesting?
From what I understand the next steps are:
Create an array of fruit.keys sorted alphabetically
Use the fruit.keys to get image.keys from 'imageMetaDict'
Use those image.keys to look up the image data (imageURL, etc) in 'imageDataDict'
Transform all of this data into a new FruitDict which contains fruitCategory -> [fruitObject]
Is this similar to what you were suggesting? I'm happy to hear any further pointers, code or suggestions you have, you've really helped me so far!
To store images Create imageDict hash-map(dictionary) with the key you getting from firebase key in image->>fruits eg: "-LOLHakW-EtqevCeHfzl" with value you are getting or the stuct you already create, now when populating fruits-->apple get key from your bowl array or dict and then use that same key to get the image from imagesDict dict(hashmap you just create earlier
now while storing data in firebase make sure each image has unique keys and store that same key in your bowl-->apple->image that way it will be fast and easy to manage as image data and fruits data are mapped using key you get while storing new image :-) if you like the solution I can explain in more dept :-) #HappyCoding
Example
firebase node
"bowl" : {
"apple" : {
"-LOLHakW-EtqevCeHfzl" : true,
"--LOLmQWLXXyiCUwDBwID" : false,
}
}
"image" : {
"fruit" : {
"-LOLHakW-EtqevCeHfzl" : {
"description" : "round orange",
"imageURL" : "https://firebasestorage.googleapis.com/1/image1"
},
"-LOLmQWLXXyiCUwDBwID" : {
"description" : "big banana",
"imageURL" : "https://firebasestorage.googleapis.com/1/image2"
}
}
}
ImageDict
"-LOLHakW-EtqevCeHfzl":{
"description" : "round orange",
"imageURL" : "https://firebasestorage.googleapis.com/1/image1"
},
"-LOLmQWLXXyiCUwDBwID" : {
"description" : "big banana",
"imageURL" : "https://firebasestorage.googleapis.com/1/image2"
}
or
{"-LOLHakW-EtqevCeHfzl":imageStruct1,
"-LOLmQWLXXyiCUwDBwID" :imageStruct2}
now to show image while populating apple
var keys = boul["apple"].allKeys;
if(boul["apple"][keys[0]]){ //value is true show image
var imageUrl = imageDict[keys[0]["imageURL"]; //if using dict
//or
var image = imageDict[key[0]].imageURL //if using struct
}
Now to store parent, categories and there image details
create a Dict called fruitsDict or whatever with dict in side of another dict making key as fruite name eg: "apple":{apples Details like image price etc} but if you only interested in storing images just create list of images which have true value eg: "apple":[key1, key2...]; (keys you get from imageDict.
Now based on your requirement like
Show all category!! then create all category from fruitDict use that as datasource
and use imageDict and fruitsDict for details
Show only specific category like based on seasonal fruits then crate list of those fruits and show those based on imageDict and fruiteDict
HappyCoding :-)
Hi I am trying to populate a view using the response obtained from service but not able to fetch the exact value out of the whole response ,
[
["product_id": PRO161519,
"name": clothes,
"brand_name": Levis,
"discountprice": 0,
"images": <__NSArrayM 0x6000002541c0>(
{
image = "HTTP://i.vinove.com/dnn/backend/uploads/954tshirt_PNG5434.png";
}
)
"category": Accessories,
"price": 23.00
]
]
ProductList-Model
import UIKit
import SpeedLog
let KImages = "images"
let KListImage = "image"
struct ProductList{
var images = ""
var itemArray = [String]()
func bindProductListDataToPopulateView(_ response:[[String:Any]])->[ProductList]{
SpeedLog.print("response value as result",response)
for items in response{
print("items values",items)
}
print("item array",itemArray)
return []
}
}
response value as result
[["image":
item Values
["image":
Kindly help me to get the values images here.
You have to use like this :
for product in products {
if let productImages = product["images"], let images = productImages as? NSArray {
for image in images {
if let image = image as? [String: String] {
print(image["image"])
}
}
}
}
More than likely that JSON response you posted will eventually find its way to you in the form of a key-value Dictionary. You then use a "key" from the JSON you posted to extract the key's corresponding "value". In the snippet you posted, the keys would be the values on the left of the colon (e.g. "product_id", "name", etc).
Now, lets say your dictionary of key-values was called "jsonDictionary". You then would extract the values like so:
let productId = jsonDictionary["product_id"]
let name = jsonDictionary["name"]
If, however, you don't have logic to deserialize that raw JSON data (that you posted in your question) into a Dictionary, then you'll have to start there instead.
I am fetching JSON data from my server. I am using Alamofire in my code to fetch data from server.
Here's how I am decoding it:
Alamofire.request(URL_GET_DATA, method: .post).responseJSON { response in
//getting json
if let json = response.result.value {
print(json)
let newsJson : NSArray = json as! NSArray
self.parseData(data: ((newsJson[0] as AnyObject).value(forKey: "message") as? String)!)
}
}
func parseData(data : String){
//traversing through all elements of the array
let newsArray: NSArray = data as! NSArray
for i in 0..<newsArray.count{
//adding hero values to the hero list
self.newsList.append(Objectnews(
id : (newsArray[i] as AnyObject).value(forKey: "id") as? String,
heading: (newsArray[i] as AnyObject).value(forKey: "heading") as? String,
description : (newsArray[i] as AnyObject).value(forKey: "description") as? String,
time_stamp : (newsArray[i] as AnyObject).value(forKey: "time_stamp") as? String,
type : (newsArray[i] as AnyObject).value(forKey: "type") as? String,
imageurl: (newsArray[i] as AnyObject).value(forKey: "imageurl") as? String
))
}
print("reloading table")
//displaying data in tableview
self.tableView.reloadData()
}
Here's the log for same. It contains the response from server and the error it is throwing:
{
error = 0;
message = (
{
description = "September 5th marks Teacher\U2019s Day in India. It is celebrated on the birthday of our second President, Sarvepalli Radhakrishnan. It is a day when we pay respect to our teachers and appreciate their contribution to the society and our individual lives and plan special surprises, have a chance to thank them for their selfless work in making the leaders for tomorrow. N.S.S. unit celebrated Teacher's day by gifting a hand made card to each Teaching and Non-Teaching Staff of P.G.D.A.V. College. We will also like to put forward a special thanks to the creative department team of N.S.S. for their terrific job in making those beautiful hand made cards. Happy Teachers' Day to All!";
heading = "Teacher's Day Celebration";
id = 16;
imageurl = "http://check.png";
"time_stamp" = "05/09/2017 22:58";
type = News;
},
{
description = "Incessant rains and floods have brought a havoc in one of India's most populous state, Bihar due to which roads have been closed, houses destroyed and crores affected. Rahat - an initiative of Goonj NGO steps in such situations helping all those in need and this time NSS PGDAV is doing their share of help by donating Via GOONJ and is organising a Collection Drive for the flood survivors. Your donation will provide shelter, food and comfort to families. Below are some of the things you can donate to help the people:-\n\n-Tarpaulins\n-Old flex and ropes\n-Mosquito nets\n-Dry ration\n-Clothing\n-Good quality blankets \n-Wooden toiletries\n-Utensils \n-Bucket\n-Torch and batteries\n-Umbrella\n-Slippers\n-Candles\n-Solar lights etc\n\nGiving is not just about making a donation. It's about making a difference! So step forward and #DONATE.\n\nDate: 4th-9th September 2017.\nVenue- Lobby/Office Area.\nTime: 10AM-1PM.\n\nFor queries contact:\nEkta- 7503894368\nJhanvi- 7838401571";
heading = "Collection Drive for Flood Affected Areas";
id = 15;
imageurl = "http://check.png";
"time_stamp" = "02/09/2017 21:34";
type = News;
},
{
description = "\"Beauty isn't about having a pretty face, it is about having a pretty soul, a pretty heart and a pretty mind.\"\n\nN.S.S. P.G.D.A.V. is honoured and takes a great pride in telling that MS. LAXMI AGARWAL will be speaking at the orientation program of N.S.S. which is set to be held on 26th August from 12:00 P.M. onwards. Ms. Laxmi Agarwal has inspired this country by her courage and has been the recipient of International Women of Courage Award by Michelle Obama. She is an epitome of bravery.\n\nWe could not have been more proud and excited to have her encourage the students and motivate them to overcome barriers and achieve what they aim for. We are sure she will fill in positive vibes around the program and will inspire us all to do what we need to do, to achieve what we dream for, and to inspire others for the same.";
heading = "NSS Orientation ";
id = 14;
imageurl = "http://check.png";
"time_stamp" = "25/08/2017 16:47";
type = News;
},
{
description = "Welcome Fresher's,\nHere is the last step for final selection to become a member of N.S.S. Team.\nIt's the Personal Interview. So following is the list of students who have to appear on August 2, 2017\n\n\n\n\n\n\nDAY 1 - AUGUST 2, 2017\U00a0\nSLOT 1- 10:00 A.M. - 11:00 A.M.\n\n\nAmit\U00a0\nAditya Sapra\U00a0\nAman Gupta\U00a0\nAadesh Sachdeva\U00a0\nAkshay Gaba\U00a0\nAkansha Sharma\U00a0\nAnjali Kataria\U00a0\nAakash\U00a0\nAbhinav Kumar Malviya\U00a0\nAnkita Rai\U00a0\nAstha Kanojia\U00a0\nAnita Mandal\U00a0\nAnchal\U00a0\nArif\U00a0\nAaftab Ahmad\U00a0\nAshish\U00a0\nAashirya Mittal\U00a0\nAnshul Saini\U00a0\nAnanya Singh\U00a0\nAbhay Goyal\U00a0\nAnshu Kumari Gupta\U00a0\nAjay Kumar\U00a0\nAaftab\U00a0\nAnjali Bhatt\U00a0\nAditi Singh\U00a0\nAnirudh Ahlawat\U00a0\nAshutosh\U00a0\nAnuradha\U00a0\nAmiza\U00a0\nAsmat Khan\U00a0\nAyushi Chadha\U00a0\nAmbujakshi Bhardwaj\U00a0\nAnubhav jain\U00a0\nAshutosh Verma\U00a0\nAbhishek Anand\U00a0\nAbhiraj\U00a0\nAkansha\U00a0\nAbhishek ranjan\U00a0\nAyesha Chauhan\U00a0\nAkansha\U00a0\n\n\nSLOT 2 - 11:00 A.M. - 12:00 P.M.\n\n\nAnkit\U00a0\nAmar Jeet Verma\U00a0\nAnshika Adlakha\U00a0\nAnkur Verma\U00a0\nAnkita\U00a0\nAditya Raj Chaudhary\U00a0\nBhavay Virmani\U00a0\nBunty Kumar\U00a0\nBhawna\U00a0\nBronika Paul\U00a0\nBarkat Ali\U00a0\nBrahmadutt\U00a0\nBadal Sharma\U00a0\nBhavnish Sharma\U00a0\nChandra Prakash Bhambhu\U00a0\nChanchal\U00a0\nChetna Garg\U00a0\nChetan Verma\U00a0\nChirag Sethi\U00a0\nChetan\U00a0\nDeependra Pal Yadav\U00a0\nDivya Agnihotri\U00a0\nDeepak Sahni\U00a0\nDrishya Wahil\U00a0\nDiksha paut\U00a0\nDevendra Yadav\U00a0\nDivya Chabra\U00a0\nDeep Singh\U00a0\nDeepankar Vaid\U00a0\nDrishti Goyal\U00a0\nEkta Shankar\U00a0\nFarzan Iqram\U00a0\nGaurav Bhatt\U00a0\nGarima Behl\U00a0\nGaurav Saini\U00a0\nGarvish Nanda\U00a0\nGaurav Kumar\U00a0\nGarima Payla\U00a0\nGauri Dhamija\U00a0\nharshit Singh\U00a0\n\n\nSLOT 3 - 12:00 P.M. - 1:00 P.M.\n\n\U00a0\U00a0\nHimanshi Sharma\U00a0\nHarsh Gupta\U00a0\nHarshit Girdhar\U00a0\nHarsh Bansal\U00a0\nHarshita Chauhan\U00a0\nHeena\U00a0\nHeena\U00a0\nIrfan Khan\U00a0\nIshu Rai\U00a0\nJaspreet kaur\U00a0\nJyoti\U00a0\nJaisny\U00a0\nJyoti Nishad\U00a0\nKrishan Kumar\U00a0\nKrishna\U00a0\nKetu\U00a0\nKrishika Arora\U00a0\nKhushboo Yadav\U00a0\nKanan Makker\U00a0\nKriti Kapoor\U00a0\nKanika Yadav\U00a0\nKiran Pachori\U00a0\nKunal Nagar\U00a0\nKhushboo Bansal\U00a0\nKunal Sharma\U00a0\nKajal\U00a0\nLalit Mohan\U00a0\nLovely Mathur\U00a0\nMitali Baisoya\U00a0\nmanisha\U00a0\nMiti Dangwal\U00a0\nMukul Puri\U00a0\nMansingh\U00a0\nManoj Meena\U00a0\nMohammad faisal\U00a0\nM. Danish Ameer\U00a0\nMohit Jain\U00a0\nMantu Babu\U00a0";
heading = "NSS Interview Day 1";
id = 13;
imageurl = "http://check.png";
"time_stamp" = "01/08/2017 22:30";
type = News;
},
{
description = "Time and tide waits for none, we all learnt this proverb in our primary school but yesterday I experienced something contradictory to my learning. I saw the time stopping and taking a moment to absorb what was happening around? And guess what was it, it was you, the participants, the audience of Sevaarth whose overwhelming response took the event to a whole new level. You made the mighty time get adrenaline rush. \nThis year we brought in many technical advancement to our NSS unit. We launched our mobile app, website. We facilitated user with many problem solving features. We had more number of volunteers than previous year. Our reach set a new record in the history of all NSS Unit with a growth rate of more than 17,000%. As Sevaarth '17 ended in a great way, we are much more inspired by the work of every people who put their day and night in making sure you get what we have to offer. We are humbled by the response of people. \nWe owe a great deal to our sponsers - Little App, PaisaWapas, DCOP, DSB, Internsala, Nestle, SelfDrives.in, CareerLauncher, Student Stories, The Education Tree, DU Beat, Drama Cafe. Thank you to all.\nWe have a aim. We have people who craves great passion. And, these two thing is advancing us to a new level each and every day. Every day, NSS puts a positive value in this society. We are here to make a better world for each and every person out there. No matter what's your race, nationality, religion, we will make sure that you get what you deserve. In the coming years, NSS Unit of P.G.D.A.V College will get into different areas of society from education to better health care by acting as a bridge by them. \nSevaarth is an opportunity to showcase the talent of people who choose stay away from limelight in front of people. Sevaarth seemed to have touched its highest point with all the fun, the immense hard work, representing our culture from a different perspective. \nWe promise to bring you a more vibrant version of Sevaarth next year. Adios! ";
heading = "Thank you";
id = 12;
imageurl = "http://check.png";
"time_stamp" = "22/01/2017 00:22";
type = News;
}
);
}
Could not cast value of type '__NSDictionaryI' (0x106456288) to 'NSArray' (0x106455e28).
(lldb)
How can I properly decode it based on the error in the log? I am using Swift.
Follow this step :
Creat a class called APIManager
Create Delegates method like this
//MARK : Custom Protocol Methods protocol
apiManagerDelegate:NSObjectProtocol {
func apiSuccessResponse(_ response: Dictionary<String, AnyObject>)
func APIFailureResponse(_ msgError: String)
}
//MARK : Custom Extension Methods
extension apiManagerDelegate {
func apiSuccessResponse(_ response: Dictionary<String, AnyObject>){
// leaving this empty
}
func APIFailureResponse(_ msgError: String){
// leaving this empty
} }
In Your View Controller , Conforms this Delegate Methods .
Defined method like this to consume web service in API Manager
func signUpAPI(firstName : String, lastName:String, email:String, password:String, confirmPwd:String, mobile:String, age:String, gender:String, signUp_type:Int) {
//Payload Dict
let payloadDict = [
"first_name" : firstName,
"last_name" : lastName,
"email" : email,
....
] as [String : Any]
//Showing activity indicator
---progressbar goes here
//Call Web API using Alamofire library
AlamoFireSharedManagerInit()
Alamofire.request(HCConstants.URL.HC_BASEURL + HCConstants.URL.SIGNUP, method: .post, parameters: payloadDict, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
do
{
//Checking For Error
if let error = response.result.error {
//Call failure delegate method
print(error)
//Stop AcitivityIndicator
self.hideHud()
self.delegate?.APIFailureResponse("Something goes wrong , Try after some time!!")
return
}
//Store Response
let responseValue = try JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions()) as! Dictionary<String, AnyObject>
print(responseValue)
//Check Success Flag
print(responseValue["success"] as! Bool)
if let mSuccessFlag = responseValue["success"] as? Bool {
//Failure message
if !mSuccessFlag {
self.delegate?.APIFailureResponse(responseValue["message"] as! String? ?? "Something goes wrong , Please try after some time")
}
//Call success delegate method
else {
self.delegate?.apiSuccessResponse(responseValue)
}
}
//Stop AcitivityIndicator
self.hideHud()
} catch {print("Sign up API fired exception")}
}
}
Above method parse the data and send it to the success or failure method to your viewcontroller and from there you need to populate the data and just render it .
Isn't it super easy ?
I am trying to add json values in JSQMessageData to show the message on JSQMessagesViewController. The view is set up and this the lite chat(can chat only once).We use an api to send and receive messages. The problem is when I fetched data from api as json it returns the value. I want to append that json data to the rest of my JSQMessages objects, I tried the last few days and have failed to accomplish this. Here is the full code and json response.
APIHandler.requestGETURL(urlString, success: { (JSON) in
print(JSON)
// var messageDictionary : [JSQMessageData] = []
// this is the message object
// i want to add the json data to my messageDictionary
// reload collection view
/*
{
"message_time" : "27-05-2017",
"user_id" : 1924,
"user_name" : "Tester name",
"message" : "hi",
"user_thumb" : "<image_path>"
},
{
"message_time" : "27-05-2017",
"user_id" : 1924,
"user_name" : "Tester name",
"message" : "how are you?",
"user_thumb" : "<image_path>"
}
*/
// i want to
let arrayNames = JSON["data"]
self.messageDictionary.append(JSQMessageData())
// I am stuck here
}) { (Error) in
print(Error.localizedDescription)
}
If I understand you correctly you're trying to parse json into a JSQMessage object. Your message data is not overly complex, it contains all the things a standard JSQMessage needs. So there is not any reason to create your own JSQMessageData object. You can just use one of the JSQMessage initializers. Since you are only using "Text" messages and not any other "Media" the
JSQMessage(senderId: <String!>, senderDisplayName: <String!>, date: <#Date>, text: <String>)
should be all you need. So all you need to do is get the values out of your json response. There are many ways to do this.
I am going to assume that the json you provided is also wrapped in a list like this
[
{ "message_time" : "27-05-2017",
"user_id" : 1924,
"user_name" : "Tester name",
"message" : "hi",
"user_thumb" : "<image_path>"
},
{ "message_time" : "27-05-2017",
"user_id" : 1924,
"user_name" : "Tester name",
"message" : "how are you?",
"user_thumb" : "<image_path>"
}
]
We can utilise the flatmap function to get our "Messages" out of the json data. You also do not need a dictionary becasue there is not key for each message so just use a list that contains JSQMessageObjects
var messages:[JSQMessages] = []
var imageDictionary: [userID: String: imagePath: String] = [:]
APIHandler.requestGETURL(urlString, success: { (JSON) in
print(JSON)
let messagesJSON = response.result.value as? [[String: Any]] ?? [[:]]
guard let listOfMessages = JSON as? [[String: AnyObject]]
messages: [JSQMessage] = listOfMessages.flatmap { messageData in
guard let dateCreated = messageData["message_time"] as? Date,
let userID = messageData["user_id"] as? String,
let userName = messageData["user_name"] as? String,
let text = messageData["message"] as? String else {
//If any of these things are missing we do not want to save the entry
return nil
}
let imagePath = messageData["user_thumb"] as? String
imageDictionary[userID] = imagePath
return JSQMessage(senderId: userID, senderDisplayName: userName, date: dateCreated, text: text)
}) { (let error: Error) in
if error != nil {
print(Error.localizedDescription)
}
}
I would save your image paths into a dictionary and fetch them on a background thread that way users can view the messages while the images populate as they arrive. Then once they have loaded apply them to your messages. or you can add it to your own custom message object that conformes to the JSQMessageDataSource protocol. for more on how to accomplish that check out this post
#Daniel is saying right, your json is enough simple that you don't need to add any JSQMessageData and maybe you are actually doing some extra effort, i have faced similar kind of problem when i need to pass a NSDictionary object with JSQMessage Objects so i used a tricky way for doing that ( and it works perfectly fine :) )
not sure about your case but this helps me a lot in many situations so follow these steps :
convert your json data into string
now save this json string into the accessebilityHint property of JSQmessage object. like -
(jsqmessageObj).accessibilityHint = jsonString
as according to your need as you want to use this json just extract the JSQmessage Object (like in cellForRowAtIndexPath ! ) , just use (jsqmessageObj).accessibilityHint to get back your json string decode it and use it as your need.
like - strJson = (jsqmessageObj).accessibilityHint
Hope this will help :p
I have the next JSON structure in Firebase:
{
"-KGX6kYg1NO6d9hn-8um" : {
"phase" : "A",
"timestamp" : "12-18-2015 19:43:37"
},
"-KGXOGSxa3vompZX9UO_" : {
"phase" : "B",
"timestamp" : "03-28-2016 15:28:21"
},
"-KMUvszD-vm3Nu02sofd" : {
"phase" : "A",
"timestamp" : "04-03-2014 03:57:56"
}
}
Is it possible to filter the objects by the timestamp key through a range of date?.. For example, I want to get the objects with timestamp from January 2015 to today date. If not possible, what's the better way to filter the objects by dates?... I'm developing an iOS app.
Thanks.
You can sort the snapshot data by timestamp and define a timestamp limit from which you want your data.
For example you want all data from a specific timestamp timestamp1, your reference handler should look like:
let refHandle = tableRef.queryOrderedByChild("timestamp").queryEndingAtValue("timestamp1").observeEventType(FIRDataEventType.Value, withBlock: { (snapshot) in
for item in snapshot.children {
}
})
You can also apply number of records that you want by adding queryLimitedToLast or queryLimitedToFirst like :
let refHandle = tableRef.queryOrderedByChild("timestamp").queryEndingAtValue("some_time_stamp").queryLimitedToLast(kPostLimit + 1).observeEventType(FIRDataEventType.Value, withBlock: { (snapshot) in
for item in snapshot.children {
}
})
Also, you want to have a look at the following post about common sql queries in Firebase.