NSMutableDictionary addEntriesFromDictionary not merging dictionaries properly - ios

I have a JSON response that I store as an NSMutableDictionary that looks like this:
{
"list": { "ID1", "ID2", "ID3" },
"items": {
"ID1" : { "name" : "shoe" },
"ID2" : { "name" : "pants" },
"ID3" : { "name" : "hat" }
}
}
i need to have the NSMutableDictionary add entries from any additional JSON responses, so if i receive a new response as follows:
{
"list": { "ID4", "ID5", "ID6" },
"items": {
"ID4" : { "name" : "shirt" },
"ID5" : { "name" : "tie" },
"ID6" : { "name" : "glasses" }
}
}
the updated NSMutableDictionary needs to appear as follows:
{
"list": { "ID1", "ID2", "ID3", "ID4", "ID5", "ID6" },
"items": {
"ID1" : { "name" : "shoe" },
"ID2" : { "name" : "pants" },
"ID3" : { "name" : "hat" },
"ID4" : { "name" : "shirt" },
"ID5" : { "name" : "tie" },
"ID6" : { "name" : "glasses" }
}
}
Unfortunately, when i call addEntriesFromDictionary with the additions, i get this:
{
"list": { "ID1", "ID2", "ID3" },
"items": {
"ID1" : { "name" : "shoe" },
"ID2" : { "name" : "pants" },
"ID3" : { "name" : "hat" }
}
}
"list": { "ID4", "ID5", "ID6" },
"items": {
"ID4" : { "name" : "shirt" },
"ID5" : { "name" : "tie" },
"ID6" : { "name" : "glasses" }
}
}

Assuming we have the same dictionaries as in your example:
let key1 = "list"
let key2 = "items"
var rec = [key1:["ID1","ID2","ID3"],
key2:["ID1":["name":"shoe"],"ID2":["name":"pants"],"ID3":["name":"hat"]]] as [String : Any]
let inc = [key1:["ID4","ID5","ID6"],
key2:["ID4":["name":"shirt"],"ID5":["name":"tie"],"ID6":["name":"glasses"]]] as [String : Any]
I used the following rationale to find a solution:
... implemented this code snippet hereafter:
func merge(_ inc:[String:Any], into rec: inout [String:Any]) -> [String:Any] {
for (_, vals) in inc {
if var recKeys = rec[key1] as? [String],
var recItems = rec[key2] as? [String:[String:String]],
let incItems = inc[key2] as? [String:[String:String]] {
if let incValIds = vals as? [String] {
for id in incValIds {
if let newVal = incItems[id] {
if recKeys.contains(id) {
for (newValId, newValObj) in newVal {
guard var tab = recItems[id] else { continue }
tab[newValId] = newValObj
recItems[id] = tab
}
} else {
recKeys.append(id)
recItems[id] = newVal
}
}
}
}
rec[key1] = recKeys
rec[key2] = recItems
}
}
return rec
}
... and used this function as described hereunder to get the result defined below:
let updatedInfo = merge(inc, into: &rec)
print(updatedInfo)
You can now properly merge the two provided dictionaries as desired.

Related

Nested Array filter swift

I'm trying to filter the data from the sub_category array and show on the data in which isSelected is true. I have tried using flatmap and filter but am still not able to achieve the desired output. Please help.
{
"data": [
{
"category_name": "Social Sites",
"sub_category": [
{
"sub_category_name": "Instagram",
"isSelected" : true
},
{
"sub_category_name": "Facebook",
"isSelected" : true
},
{
"sub_category_name": "Twitter",
"isSelected" : false
}
]
},
{
"category_name": "",
"sub_category": [
{
"sub_category_name": "State",
"isSelected" : false
}
]
},
{
"category_name": "Sports",
"sub_category": [
{
"sub_category_name": "Cricket",
"isSelected" : true
},
{
"sub_category_name": "Hockey",
"isSelected" : false
}
]
}
]
}
Desired Output is only for isSelected = true
{
"data": [
{
"category_name": "Social Sites",
"sub_category": [
{
"sub_category_name": "Instagram",
"isSelected" : true
},
{
"sub_category_name": "Facebook",
"isSelected" : true
}
]
},
{
"category_name": "Sports",
"sub_category": [
{
"sub_category_name": "Cricket",
"isSelected" : true
}
]
}
]
}
I have tried using flatMap and filter, the following is my code.(But not able to achieve the desired output.)
let filtered = self.itemModelArray.flatMap { item in
item.subCategory!.filter({ (subCat) -> Bool in
subCat.isSelected == true
})
}
The above code gives me the array of subCategory,that is not what I want.
The following is my model
// MARK: - Item
struct Item: Codable {
let category_name: String
var sub_category: [SubCategory]
init(cat:String,subCat:[SubCategory]){
self.category_name = cat
self.sub_category = subCat
}
}
// MARK: - SubCategory
struct SubCategory: Codable {
let sub_category_name: String
var isSelected : Bool = false
init(subCat:String){
self.sub_category_name = subCat
}
Something like this would filter out both empty categories & non-selected sub-categories:
import Foundation
let json: String = <the json in the question, omited for brevity>
struct Model: Codable {
let data: [Category]
struct Category: Codable {
let category_name: String
let sub_category: [SubCategory]
}
struct SubCategory: Codable {
let sub_category_name: String
let isSelected: Bool
}
}
// Note: Handle any errors properly in production code
let model = try? JSONDecoder().decode(Model.self, from: Data(json.utf8))
var output: [Model.Category] = []
for category in model?.data ?? [] {
let selectedSubCategories = category.sub_category.filter(\.isSelected)
if !selectedSubCategories.isEmpty {
output.append(Model.Category(category_name: category.category_name, sub_category: selectedSubCategories))
}
}
which produces an array of 2 categories:
dump(output)
▿ 2 elements
▿ main.Model.Category
- category_name: "Social Sites"
▿ sub_category: 2 elements
▿ main.Model.SubCategory
- sub_category_name: "Instagram"
- isSelected: true
▿ main.Model.SubCategory
- sub_category_name: "Facebook"
- isSelected: true
▿ main.Model.Category
- category_name: "Sports"
▿ sub_category: 1 element
▿ main.Model.SubCategory
- sub_category_name: "Cricket"
- isSelected: true

Swift 5 Json Parse from post Request

I am trying to parse JSON data from a post request and I am struggling with the outcome. I would like to parse the JSON data in the Swift 5 programming language.
I have spent hours trying to figure this out. I am very confused on how to deal with multiple levels of hiarchy like this.
I dont need all the data i just need time and total_amount_sent.
Swift
struct Response: Codable {
var txs: [ResponseData]
enum CodingKeys: String, CodingKey {
case txs
}
}
struct ResponseData: Codable {
var time: String?
var total_amount_sent: String?
var recipient: String?
var txid: String?
var amount: String?
}
let url = URL(string: paramURL)!
let json: [String: Any] = [
"key": "value"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: json)
let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in
do {
let json = try JSONDecoder().decode(Response.self, from: data!)
print(json)
json.txs.forEach { charge in
let transaction_time = charge.time
let transaction_txid = charge.txid
let transaction_total_amount_sent = charge.total_amount_sent
print(transaction_time)
print(transaction_txid)
print(transaction_total_amount_sent)
}
} catch {
print("Error! \(error)")
}
})
task.resume()
Error:
Error! keyNotFound(CodingKeys(stringValue: "txs", intValue: nil),
Swift.DecodingError.Context(codingPath: [], debugDescription: "No
value associated with key CodingKeys(stringValue: "txs", intValue:
nil) ("txs").", underlyingError: nil))
JSON:
{
"status" : "success",
"data" : {
"network" : "DOGETEST",
"txs" : [
{
"txid" : "df4ac3ecfc356d9e10325cd4043a4103602599b71a91ea96cb3fa3204c61264c",
"from_green_address" : false,
"time" : 1620076250,
"confirmations" : 5,
"amounts_received" : [
{
"recipient" : "2N3ZbAaJqtxD5jfbLDZichV6SSHZ6PBYPmi",
"amount" : "2.00000000"
}
],
"senders" : [
"2MtSgfBmXzZv6raD7yyuGzFamzBzQD7G6Rf"
],
"confidence" : 1.0,
"propagated_by_nodes" : null
},
{
"txid" : "d983739751a6170d336016ffa1b7d7f2849a4a81cb0021e03a2cc6d76c55379d",
"from_green_address" : false,
"time" : 1620076071,
"confirmations" : 6,
"amounts_received" : [
{
"recipient" : "2N3ZbAaJqtxD5jfbLDZichV6SSHZ6PBYPmi",
"amount" : "2.00000000"
}
],
"senders" : [
"2MtSgfBmXzZv6raD7yyuGzFamzBzQD7G6Rf"
],
"confidence" : 1.0,
"propagated_by_nodes" : null
},
{
"txid" : "1dce7dd99f6a655ca82a94c8e088576c78e4ece94995f2f90891b8f5f31a54db",
"from_green_address" : false,
"time" : 1620076021,
"confirmations" : 6,
"amounts_received" : [
{
"recipient" : "2N3ZbAaJqtxD5jfbLDZichV6SSHZ6PBYPmi",
"amount" : "8.00000000"
}
],
"senders" : [
"2MtSgfBmXzZv6raD7yyuGzFamzBzQD7G6Rf"
],
"confidence" : 1.0,
"propagated_by_nodes" : null
},
{
"txid" : "27719e8fae3bb64f1ecec8ac64a2135d1ccc5d9219040dceaec9d24e4b17a466",
"from_green_address" : false,
"time" : 1620075780,
"confirmations" : 6,
"amounts_received" : [
{
"recipient" : "2N3ZbAaJqtxD5jfbLDZichV6SSHZ6PBYPmi",
"amount" : "4.00000000"
}
],
"senders" : [
"2MtSgfBmXzZv6raD7yyuGzFamzBzQD7G6Rf"
],
"confidence" : 1.0,
"propagated_by_nodes" : null
},
{
"txid" : "2a6547411b15442b78b118981cf5632e3faedec8941aea22453d8837807d37be",
"from_green_address" : false,
"time" : 1620075743,
"confirmations" : 7,
"amounts_received" : [
{
"recipient" : "2N3ZbAaJqtxD5jfbLDZichV6SSHZ6PBYPmi",
"amount" : "2.00000000"
}
],
"senders" : [
"2MtSgfBmXzZv6raD7yyuGzFamzBzQD7G6Rf"
],
"confidence" : 1.0,
"propagated_by_nodes" : null
},
{
"txid" : "63a145cbdc48c1e644fa52a30ed26d66c58b685698104a549001d0fe539816ba",
"from_green_address" : false,
"time" : 1620075697,
"confirmations" : 7,
"amounts_received" : [
{
"recipient" : "2N3ZbAaJqtxD5jfbLDZichV6SSHZ6PBYPmi",
"amount" : "4.00000000"
}
],
"senders" : [
"2MtSgfBmXzZv6raD7yyuGzFamzBzQD7G6Rf"
],
"confidence" : 1.0,
"propagated_by_nodes" : null
},
{
"txid" : "ff350583e0cb1396a3d5cc09350697daf111626ec5a3b893f8e936276f1c6715",
"from_green_address" : false,
"time" : 1620075677,
"confirmations" : 7,
"amounts_received" : [
{
"recipient" : "2N3ZbAaJqtxD5jfbLDZichV6SSHZ6PBYPmi",
"amount" : "2.00000000"
}
],
"senders" : [
"2MtSgfBmXzZv6raD7yyuGzFamzBzQD7G6Rf"
],
"confidence" : 1.0,
"propagated_by_nodes" : null
},
{
"txid" : "5a0115a9f608f3d01caee03587253fc58e0ad0c602f4e95e6c0db1e11703af84",
"from_green_address" : false,
"time" : 1619998414,
"confirmations" : 227,
"amounts_received" : [
{
"recipient" : "2N3ZbAaJqtxD5jfbLDZichV6SSHZ6PBYPmi",
"amount" : "1000.00000000"
}
],
"senders" : [
"2MytwDpHWpdoVYQ7JzYwBPxQ5XsEdiV7udZ"
],
"confidence" : 1.0,
"propagated_by_nodes" : null
}
]
}
}
Your model was not properly structured.
struct Response: Decodable {
var txs: [ResponseData]
enum CodingKeys: CodingKey {
case data
}
enum ValueCodingKeys: CodingKey {
case txs
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let nestedContainer = try container.nestedContainer(keyedBy: ValueCodingKeys.self, forKey: .data)
txs = try nestedContainer.decode([ResponseData].self, forKey: .txs)
}
}
struct ResponseData: Decodable {
var time: Int?
var txid: String?
var amountsReceived: [AmoutReceived]
}
struct AmoutReceived: Decodable {
var recipient: String?
var amount: String?
}
Use .convertFromSnakeCase.
Hope you are handling error cases properly. Here is the code
func fetch(urlString: String, callback: #escaping (Result<Response, Error>) -> Void) {
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else {
if let error = error {
callback(.failure(error))
}
return
}
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode(Response.self, from: data)
callback(.success(result))
} catch {
callback(.failure(error))
}
}.resume()
}
You can use tools such as Quicktype.io to create a model from a JSON. This is an example model from your provided JSON. You can play around with this tool, and also there is an option "Renders output in a Swift 5 compatible mode" since you are asking about parsing in Swift 5 programming language.
import Foundation
struct User: Codable {
let status: String
let data: DataClass
}
struct DataClass: Codable {
let network: String
let txs: [Tx]
}
struct Tx: Codable {
let txid: String
let fromGreenAddress: Bool
let time, confirmations: Int
let amountsReceived: [AmountsReceived]
let senders: [String]
let confidence: Int
let propagatedByNodes: JSONNull?
enum CodingKeys: String, CodingKey {
case txid
case fromGreenAddress = "from_green_address"
case time, confirmations
case amountsReceived = "amounts_received"
case senders, confidence
case propagatedByNodes = "propagated_by_nodes"
}
}
struct AmountsReceived: Codable {
let recipient, amount: String
}
class JSONNull: Codable, Hashable {
public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
return true
}
public var hashValue: Int {
return 0
}
public init() {}
public required init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if !container.decodeNil() {
throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encodeNil()
}
}

Group a dictionary with same type into an array with full key and value using Swift

it's been a long time I don't use Swift.
I have a response data like this and I saved it into an array named responseData:
[
{
"type": "Switch",
"name": "Switch1",
"search_key": "is_promotion",
"key": "is_promotion=1",
"icon": ""
},
{
"type": "Switch",
"name": "Switch2",
"search_key": "shop_type",
"key": "shop_type=2",
"icon": ""
},
{
"type": "Switch",
"name": "Switch3",
"search_key": "is_certified",
"key": "is_certified=1",
"icon": ""
},
{
"type": "Switch",
"name": "Switch4",
"search_key": "shop_free_shipping",
"key": "shop_free_shipping=1",
"icon": ""
},
{
"type": "Switch",
"name": "Switch5",
"search_key": "is_loyalty",
"key": "is_loyalty=1",
"icon": ""
},
{
"type": "Switch",
"name": "Switch6",
"search_key": "is_using_instant",
"key": "is_using_instant=1",
"icon": ""
},
{
"type": "Switch",
"name": "Switch7",
"search_key": "is_installment",
"key": "is_installment=1",
"icon": ""
},
{
"type": "Range",
"name": "Price Range",
"search_key": "level_Price_Max_Min",
"value": [
{
"option_id": 0,
"option_name": 0
},
{
"option_id": 0,
"option_name": 10000000
}
]
},
{
"type": "ColorTerm",
"name": "Color",
"search_key": "color_key",
"value": [
{
"option_id": 605,
"value": "Black",
"color_id": 13,
"image": "",
"option_name": "Black",
"background": "#000000",
"option_active": "",
"facet_count": 52655
},
Now I wanna group all dictionary with type Switch into one array and I can access to the keys inside it, then present data of both Switch type array and the others type on a UITableView which have 2 section (Switch type in section 0). How can I do it? I have to search some other solution but I don't understand how to apply them to my code for work.
Here is my FilterModel class:
class FilterModel: NSObject, NSCoding, NSCopying {
override func copy(with zone: NSZone? = nil) -> Any {
// This is the reason why `init(_ model: GameModel)`
// must be required, because `GameModel` is not `final`.
let copy = FilterModel(dict: self.dictionary)
if let arrAttribute = NSArray(array: self.value , copyItems: true) as? [AttributeValueModel] {
copy.value = arrAttribute
}
return copy
}
override init(dict: Dictionary<String, Any>) {
super.init(dict: dict);
value = self.valueParse()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
var name: String? {
return self.dictionary.getString(forKey: "name")
}
var icon: String? {
return self.dictionary.getString(forKey: "icon")
}
var search_key: String? {
return self.dictionary.getString(forKey: "search_key")
}
var key: String? {
return self.dictionary.getString(forKey: "key")
}
var type: FilterDisplayType {
let type = self.dictionary.getString(forKey: "type")
return self.getType(string: type)
}
var value: [AttributeValueModel] = [];
func valueParse()-> [AttributeValueModel] {
// with switch type, Just set true or false
// Change ParentValue to Child
if type == .Switch {
let dict:Dictionary<String, AnyObject> = [
"option_id": "false" as AnyObject,
"option_name": self.name! as AnyObject,
"name": self.name! as AnyObject,
"icon": self.icon! as AnyObject
]
let item = AttributeValueModel(dict:dict);
return [item]
}
guard let childs = (self.dictionary["value"]) as? [Dictionary<String, AnyObject>]
else { return [] }
var output: [AttributeValueModel] = [];
for aDict in childs {
let item = AttributeValueModel(dict:aDict);
if type == .Range && item.option_id == "0" {
item.setRangeOptionID(aValue: item.option_name!)
}
output.append(item);
}
return output;
}
///get list AttributeValueModel Selected
func selectedValues() -> [AttributeValueModel] {
var output: [AttributeValueModel] = [];
for itemTemp in self.value {
if(itemTemp.selected){
if type == .Switch {
itemTemp.setSelectedOptionID()
}
output.append(itemTemp);
}
}
return output;
}
/// make a Filter Item from attributeValues Seleted
func getFilterItem() -> FilterItem? {
var itemFilter: FilterItem = FilterItem(key: self.search_key!, value: "")
itemFilter.key = self.search_key!
let output: NSMutableArray = [];
for attItem in self.selectedValues() {
if attItem.option_id != "" {
output.add(attItem.option_id!);
}
}
if(output.count == 0) {
return nil;
}
let valueString = output.componentsJoined(by: ",");
itemFilter.value = valueString;
return itemFilter
}
///get list AttributeValueModel Selected
func resetToDefault() -> [AttributeValueModel] {
var output: [AttributeValueModel] = [];
for itemTemp in self.value {
if(itemTemp.selected){
itemTemp.selected = false
if type == .Switch {
itemTemp.setSelectedOptionID()
}
if type == .Range {
itemTemp.setRangeOptionID(aValue: itemTemp.option_name!)
}
output.append(itemTemp);
}
}
return output;
}
//for UI
var wasExpanding = false
var numberOfRow:Int = 0
/************/
var attributeNameLength: Int {
var string = ""
for item in valueParse() {
string += item.option_name!
}
return string.count
}
var lenghtSizeName:Int {
var row:Int = 1
var width:CGFloat = 0
let padding:CGFloat = 8
let screen = screenWidth - 50 - 16
for item in valueParse() {
let size = ((item.option_name ?? "") as NSString).size(withAttributes: [
NSAttributedStringKey.font : UIFont.fontRegular_Big()
])
let totalWidth = size.width + padding + 16
if totalWidth <= CGFloat(32) {
width += 32
if width >= screen {
row += 1
width = 32
}
} else {
width += totalWidth
if width >= screen {
row += 1
width = totalWidth
}
}
}
return row
}
}
You can filter your response data to get only switches in an array.
responseData.filter {($0.type ?? "") == "Switch"}
And of course != would give you non switches.

how to json list after converting into json

i am trying this but getting error . whats other way to sort this list of items .
getting error Value of tuple type
'(String, JSON)' has no member 'subscript'
let jsonData = try JSONSerialization.data(withJSONObject: bizSnapshot.value as Any, options: .prettyPrinted)
var bizOfferingsJson = try JSON(data: jsonData)
bizOfferingsJson items contains itemIndex as key as Int , i want to sort based on that itemIndex
bizOfferingsJson = bizOfferingsJson.sorted(by: { $0.["itemIndex"] > $1.["itemIndex"] })
print("bizOfferingsJson===",bizOfferingsJson)
sample bizOfferingsJson data
[
{
"isVisible" : true,
"itemRetailInfo" : {
"units" : "GRAMS",
"quantityPrice" : [
{
"discountPrice" : 0,
"regularPrice" : 25,
"quantity" : 1000,
"quantitySelected" : 1000,
"isEditable" : false
}
]
},
"imageStoragePathList" : [
"ONION_RED.png"
],
"bizOfferingsID" : "Vegetables_0",
"masterImage" : 0,
"vegNonVegInfoEnum" : "NONE",
"description" : "",
"itemQunatitySelected" : 0,
"bizOfferingsHeaderTypeThree" : {
"indexOrder" : 0,
"headerText" : "Vegetables",
"isVisible" : true
},
"itemIndex" : 0,
"totalCountQunatity" : 0,
"primaryText" : "Onion Red"
},
{
"isVisible" : true,
"itemRetailInfo" : {
"units" : "GRAMS",
"quantityPrice" : [
{
"discountPrice" : 0,
"regularPrice" : 25,
"quantity" : 1000,
"quantitySelected" : 1000,
"isEditable" : false
}
]
},
"imageStoragePathList" : [
"POTATO.png"
],
"bizOfferingsID" : "Vegetables_1",
"masterImage" : 0,
"vegNonVegInfoEnum" : "NONE",
"description" : "",
"itemQunatitySelected" : 0,
"bizOfferingsHeaderTypeThree" : {
"indexOrder" : 0,
"headerText" : "Vegetables",
"isVisible" : true
},
"itemIndex" : 1,
"totalCountQunatity" : 0,
"primaryText" : "Potato"
},
{
"isVisible" : true,
"itemRetailInfo" : {
"units" : "PIECES",
"quantityPrice" : [
{
"discountPrice" : 0,
"regularPrice" : 3,
"quantity" : 1,
"quantitySelected" : 0.10000000000000001,
"isEditable" : false
}
]
},
"imageStoragePathList" : [
"CORIANDER_LEAVES_BUNCH.png"
],
"bizOfferingsID" : "Vegetables_2",
"masterImage" : 0,
"vegNonVegInfoEnum" : "NONE",
"description" : "",
"itemQunatitySelected" : 0,
"bizOfferingsHeaderTypeThree" : {
"indexOrder" : 0,
"headerText" : "Vegetables",
"isVisible" : true
},
"itemIndex" : 2,
"totalCountQunatity" : 0,
"primaryText" : "Coriander Leaves Bunch"
},
{
"isVisible" : true,
"itemRetailInfo" : {
"units" : "GRAMS",
"quantityPrice" : [
{
"discountPrice" : 0,
"regularPrice" : 8,
"quantity" : 500,
"quantitySelected" : 500,
"isEditable" : false
}
]
},
"imageStoragePathList" : [
"TOMATO_STANDARD.png"
],
"bizOfferingsID" : "Vegetables_3",
"masterImage" : 0,
"vegNonVegInfoEnum" : "NONE",
"description" : "",
"itemQunatitySelected" : 0,
"bizOfferingsHeaderTypeThree" : {
"indexOrder" : 0,
"headerText" : "Vegetables",
"isVisible" : true
},
"itemIndex" : 3,
"totalCountQunatity" : 0,
"primaryText" : "Tomato Standard"
}
]
You need to clarify which type you sort assuming an array
var bizOfferingsJson = try JSON(data: jsonData).array!
bizOfferingsJson = bizOfferingsJson.sorted(by: { $0["itemIndex"] > $1["itemIndex"] })
or using mutating sort
bizOfferingsJson.sort{ $0["itemIndex"] > $1["itemIndex"] }
using Codable is much better given your json
struct Root: Codable {
let isVisible: Bool
let itemRetailInfo: ItemRetailInfo
let imageStoragePathList: [String]
let bizOfferingsID: String
let masterImage: Int
let vegNonVegInfoEnum, purpleDescription: String
let itemQunatitySelected: Int
let bizOfferingsHeaderTypeThree: BizOfferingsHeaderTypeThree
let itemIndex, totalCountQunatity: Int
let primaryText: String
enum CodingKeys: String, CodingKey {
case isVisible, itemRetailInfo, imageStoragePathList, bizOfferingsID, masterImage, vegNonVegInfoEnum
case purpleDescription = "description"
case itemQunatitySelected, bizOfferingsHeaderTypeThree, itemIndex, totalCountQunatity, primaryText
}
}
// MARK: - BizOfferingsHeaderTypeThree
struct BizOfferingsHeaderTypeThree: Codable {
let indexOrder: Int
let headerText: String
let isVisible: Bool
}
// MARK: - ItemRetailInfo
struct ItemRetailInfo: Codable {
let units: String
let quantityPrice: [QuantityPrice]
}
// MARK: - QuantityPrice
struct QuantityPrice: Codable {
let discountPrice, regularPrice, quantity: Int
let quantitySelected: Double
let isEditable: Bool
}
var res = try! JSONDecoder().decode([Root].self, from: jsonData)
res.sort { $0.itemIndex > $1.itemIndex }

How to retrieve data from each child in Firebase?

I'm trying to retrieve all the values that I have in each post (post_text, timestamp, username) to be used in a Table View using Swift. I have tried this code but wasn't sure where to go from here to get each value from posts.
ref.observeEventType(.Value, withBlock: { snapshot in
self.posts = snapshot.value.objectForKey("posts") as! [String: String]
print(self.posts)
self.tableView.reloadData()
})
The JSON Firebase file:
{
"posts" : {
"-KAqlyZ71SNZfZ4Zbs27" : {
"post_text" : "Hello",
"timestamp" : 1455839242909,
"username" : "hello"
},
"-KAqmD6HPbhAVkjT54-k" : {
"post_text" : "Hi",
"timestamp" : 1455839306600,
"username" : "user7"
},
"-KAr9ATmAjObiTsn4yUC" : {
"post_text" : "Hi",
"timestamp" : 1455845587135,
"username" : "user7"
},
"-KArIBlnKSJWGhD9Me6T" : {
"post_text" : "Dddd",
"timestamp" : 1455847983983
}
},
"users" : {
"5476cde6-b343-476d-abb7-8131d3766ba7" : {
"email" : "ad#ad.com",
"posts" : {
"-KAm_8ShLSKrKKMhNjpm" : {
"post_text" : "Hello :)",
"timestamp" : 1455768771004
}
},
"provider" : "password",
"username" : "ad"
},
"b7b7de04-e180-4cac-abd3-57c016640e32" : {
"email" : "user#user.com",
"posts" : {
"-KAqmD6HPbhAVkjT54-l" : {
"post_text" : "Hi",
"timestamp" : 1455839306869
},
"-KAr9ATq-MEkYmAr2SB_" : {
"post_text" : "Hi",
"timestamp" : 1455845587513
},
"-KArIBlxY-FvbsmgF5bI" : {
"post_text" : "Dddd",
"timestamp" : 1455847985342
}
},
"provider" : "password",
"username" : "user7"
},
"fb67da22-e0dd-4ced-873b-53a588d78feb" : {
"email" : "hello#hi.com",
"posts" : {
"-KAqlyZAah6bclwqWi5M" : {
"post_text" : "Hello",
"timestamp" : 1455839243184
}
},
"provider" : "password",
"username" : "hello"
}
}
}
How could I do this?
You can just create an object Post that can be initialized by a Dictionary. Then, just fetch the single key with his value.
var posts : [Post] = []()
json.forEach { (key, dictionary) -> in
let post = Post(
key: key,
dictionary: dictionary
)
posts.append(post)
}

Resources