I am Getting a Dynamic Array which Consist (Dictionary with Array ) and want to increase the Index of Array and will go on to Next Dictionary on action.
After Parsing The Value in swapLibs
var currentQuizIndex = 0
func Dataparsed() {
ServiceManager.service(ServiceType.POST, path: urslStr, param: nil, completion: { (sucess, response, error, code) -> Void in
if (code == 200) {
let QuizData = (swapLibs?.valueForKey("quiz") as! NSArray)
let quizData = playInfo.PlayQuizInfo(QuizData[self.currentQuizIndex] as? NSDictionary)
self.playQuizArray.addObject(quizData)
self.playQuizTitle?.text = quizData.quizQuestion
self.playQImage.sd_setImageWithURL(NSURL(string: quizData.quizQImage!))
self.QNumber?.text = "\(self.Qno)/\(self.noofQuestion)"
}
})
}
And The Modal is
class playInfo: NSObject {
var quizId : String? = ""
var quizQId : String? = ""
var quizQImage : String? = ""
var quizQuestion : String? = ""
var quizType : String? = ""
var quizIndex : String? = ""
class func PlayQuizInfo(dict: NSDictionary?) -> playInfo {
let Pinfo = playInfo()
Pinfo.WrapPlayQuiz(dict)
return Pinfo
}
func WrapPlayQuiz(dict: NSDictionary?) {
if dict == nil {
return
}
self.quizId = dict!.objectForKey("quizId") as? String
self.quizIndex = dict!.objectForKey("index") as? String
self.quizQImage = dict!.objectForKey("QuesImage") as? String
self.quizQuestion = dict!.objectForKey("question") as? String
self.quizType = dict!.objectForKey("Type") as? String
self.quizQId = dict!.objectForKey("questionId") as? String
}
}
Here is Structure
{
"quiz":[
{
"quizId":"7295",
"QuesImage":"http:\/\/proprofs.com\/api\/ckeditor_images\/man-approaches-woman1(1).jpg",
"question":"How do you know him?",
"questionId":"216210",
"Type":"PQ",
"index":4,
"keys":[
{
"answerId":"8266",
"option":"He's in one or more of my classes, and we're good friends.",
"AnsImage":"Image Not Available"
},
{ },
{ },
{ },
{ }
]
},
{ },
{ },
{ },
{ },
{ },
{ },
{ },
{ },
{ },
{ },
{ }
]
}
Each Dictionary is Containing same Key As above
Any Help Will Be Appreciated.Thanks.
As I don't have ServiceManager at my end so I have created this code hypothetically. It might solve you issue of saving all data in to one array. It also adds keys in to array as an object.
EDIT 1 : correct QuizKey object array formation. Let me know if any kind of error occurs, as I am unable to test it at my end.
Edit 2: I have made a general ViewController its working perfectly.Try running this View Controller file and you will see the results.
class TestVC: UIViewController {
//An Array similar to the response you are getting from the server
var response:[AnyObject] = [
[
"quizId" : "1111",
"QuesImage" : "http://proprofs.com/api/ckeditor_images/man-approaches-woman1(1).jpg",
"question" : "How do you know him?",
"questionId" : "216210",
"Type" : "PQ",
"index" : 4,
"keys":[
[
"answerId":"8266",
"option":"He's in one or more of my classes, and we're good friends.",
"AnsImage":"Image Not Available"
],
[
"answerId":"8266",
"option":"He's in one or more of my classes, and we're good friends.",
"AnsImage":"Image Not Available"
],
[
"answerId":"8266",
"option":"He's in one or more of my classes, and we're good friends.",
"AnsImage":"Image Not Available"
]
]
],
[
"quizId" : "2222",
"QuesImage" : "http://proprofs.com/api/ckeditor_images/man-approaches-woman1(1).jpg",
"question" : "How do you know him?",
"questionId" : "216210",
"Type" : "PQ",
"index" : 4,
"keys":[
[
"answerId":"8266",
"option":"He's in one or more of my classes, and we're good friends.",
"AnsImage":"Image Not Available"
],
[
"answerId":"8266",
"option":"He's in one or more of my classes, and we're good friends.",
"AnsImage":"Image Not Available"
],
[
"answerId":"8266",
"option":"He's in one or more of my classes, and we're good friends.",
"AnsImage":"Image Not Available"
]
]
]
]
var playQuizArray:[playInfo]! = []
override func viewDidLoad() {
super.viewDidLoad()
print(response)
for dict in response {
self.playQuizArray.append(playInfo.PlayQuizInfo(dict as? [String:AnyObject]))
}
print(self.playQuizArray)
let quiz = self.playQuizArray[0]
print("quizId \(quiz.quizId)")
print("keyAnswerId \(quiz.quizKeys![0].keyAnswerId)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
class playInfo: NSObject {
var quizId : String? = ""
var quizQId : String? = ""
var quizQImage : String? = ""
var quizQuestion : String? = ""
var quizType : String? = ""
var quizIndex : String? = ""
//quizKeys will contain quiz array
var quizKeys : [QuizKey]? = []
class func PlayQuizInfo(dict: [String:AnyObject]?) -> playInfo {
let Pinfo = playInfo()
Pinfo.WrapPlayQuiz(dict)
return Pinfo
}
func WrapPlayQuiz(dict: [String:AnyObject]?) {
if dict == nil {
return
}
self.quizId = dict!["quizId"] as? String
self.quizIndex = dict!["index"] as? String
self.quizQImage = dict!["QuesImage"] as? String
self.quizQuestion = dict!["question"] as? String
self.quizType = dict!["Type"] as? String
self.quizQId = dict!["questionId"] as? String
//add key object array to the quizKeys
if let arrKeys = dict!["keys"] as? [AnyObject] {
for arr in arrKeys {
let key:QuizKey = QuizKey.QuizKeyInfo(arr as? [String : AnyObject])
self.quizKeys?.append(key)
}
}
}
}
class QuizKey: NSObject {
var keyAnswerId : String? = ""
var keyOption : String? = ""
var keyAnsImage : String? = ""
class func QuizKeyInfo(dict: [String:AnyObject]?) -> QuizKey {
let QKeys = QuizKey()
QKeys.WrapQuizKeys(dict)
return QKeys
}
func WrapQuizKeys(dict: [String:AnyObject]?) {
if dict == nil {
return
}
self.keyAnswerId = dict!["answerId"] as? String
self.keyOption = dict!["option"] as? String
self.keyAnsImage = dict!["AnsImage"] as? String
}
}
Related
I am trying to pass data into variable by displaying it(NameList and BasketDetail). But the basket data is empty(BasketDetail). How can i solve this (Output:Retrieve data: [“name”: Mike, “basket”: <__NSArray0 0x28112c060()])?
Firebase node;
"Pro_" : {
"-MsVcfY7pZI74r0E1ULD" : {
"basket" : {
"-Mruf-UdXxpLK0l8Qgw4" : {
"cat" : "Tech",
"info" : "iOS",
"orderid" : "Ref_1",
},
"-MszuLj3cxm_gE9m-VPO" : {
"cat" : "Tech",
"info" : "Android",
"orderid" : "Ref_2",
}
},
"name" : "-Mike",
}
}
My function;
private func populateNameLists() {
ref = Database.database().reference()
self.ref.child(“Pro_”).observeSingleEvent(of:.value) { (snapshot) in
self.nameLists.removeAll()
let nameListDictionary = snapshot.value as? [String:Any] ?? [:]
for (key,_) in nameListDictionary {
if let nameListDictionary = nameListDictionary[key] as? [String:Any] {
if let nameList = NameList(nameListDictionary) {
self.nameLists.append(nameList)
print(“Retrieve data:”, try! nameList.toDictionary())
}}}}}
Output(Basket's empty ???)
Retrieve data: [“name”: Mike, “basket”: <__NSArray0 0x28112c060()]
Name List
typealias JSONDictionary = [String:Any]
class NameList : Codable {
var basket :[BasketDetail] = [BasketDetail]()
var name: String!
init(name:String ) {
self.name = name
}
init?(_ dictionary :[String:Any]) {
guard let name = dictionary[“name”] as? String else {
return nil
self.name = name
let basketItemsDictionary = dictionary[“basket”] as? [JSONDictionary]
if let dictionaries = basketItemsDictionary {
self.basket = dictionaries.compactMap(BasketDetail.init)
}}}
Basket Detail
class BasketDetail : Codable{
var cat : String
var info : String
var orderid : String
init(cat :String, info :String, orderid :String) {
self.cat = cat
self.info = info
self.orderid = orderid
}
init?(dictionary :JSONDictionary) {
guard let cat = dictionary["cat"] as? String else {
return nil
}
guard let info = dictionary["info"] as? String else {
return nil
}
guard let orderid = dictionary["orderid"] as? String else {
return nil
}
self.cat = cat
self.info = info
self.orderid = orderid
}}
Here is my Json:
[ {
"id": 6854,
"name": "Laundry Iron",
"images": [
{
"id": 6856,
"src": "https://abcd.com/yzx/uploads/1750.jpg",
}
],
} ]
how do we make model class for getting "images":["src": "String" ]?. I want to grab "src" I have tried doing like , but it is not working :
class ProductModel {
var title: String?
var regularPrice: Int?
var salePrice: Int?
var productDescroption: String?
var imageUrl: [ImageUrl]?
init(productJsonL: NSDictionary) {
self.title = productJsonL["name"] as? String
self.regularPrice = productJsonL["regular_price"] as? Int
self.salePrice = productJsonL["sale_price"] as? Int
self.productDescroption = productJsonL["description"] as? String
//The problem is here ........
//self.imageUrl = productJsonL["images"]![0]!["src"] as? String
self.imageUrl = ImageUrl(imageUrlJson: (productJsonL["images"]![0] as? NSDictionary)!)
}
}
class ImageUrl {
var source: String?
init(imageUrlJson: NSDictionary) {
self.source = imageUrlJson["src"] as? String
}
}
please correct me with the structure like I have done above so that i can append everything at once in an array ? Thank you in advance!!
You need Codable
struct Root: Codable {
let id: Int
let name: String
let images: [Image]
}
struct Image: Codable {
let id: Int
let src: String // or let src: URL
}
do {
let res = try JSONDecoder().decode([Root].self, from: data)
print(res)
}
catch {
print(error)
}
I want to implement filter on both the parent and child, as if search 'chicken2' result should return only lines with meal as 'chicken2' + meals with name 'chicken2', below are my model classes with query and result.
import Foundation
import RealmSwift
class Canteen: Object {
#objc dynamic var name: String?
let lines = List<Line>()
func initWithJSON(json: [String: Any]) {
self.name = json["name"] as? String
let lines = json["lines"] as! [[String: Any]]
for lineJSON in lines {
let line = Line()
line.initWithJSON(json: lineJSON)
self.lines.append(line)
}
}
override static func primaryKey() -> String? {
return "name"
}
}
class Line: Object {
#objc dynamic var name: String?
var meals = List<Meal>()
let canteens = LinkingObjects(fromType: Canteen.self, property: "lines")
func initWithJSON(json: [String: Any]) {
self.name = json["name"] as? String
let meals = json["meals"] as! [[String: Any]]
for mealJSON in meals {
let meal = Meal()
meal.initWithJSON(json: mealJSON)
self.meals.append(meal)
}
}
override static func primaryKey() -> String? {
return "name"
}
}
class Meal: Object {
#objc dynamic var name: String?
#objc dynamic var vegan: Bool = false
let lines = LinkingObjects(fromType: Line.self, property: "meals")
func initWithJSON(json: [String: Any]) {
self.name = json["name"] as? String
self.vegan = json["isVegan"] as! Bool
}
override static func primaryKey() -> String? {
return "name"
}
}
Below is my controller class's viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
let file = Bundle.main.path(forResource: "mealss", ofType: ".json")
let data = try! Data(contentsOf: URL(fileURLWithPath: file!))
let json = try! JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)
if let dict = json as? [String: Any] {
let canteen = Canteen()
canteen.initWithJSON(json: dict)
try! realm.write {
realm.add(canteen, update: true)
}
}
realm.objects(Line.self).filter("ANY meals.name contains 'chicken2'")
print(lines.description)
}
below is the output of my print statement.
Below is the json file which i have used.
{
"name": "canteen1",
"lines": [
{
"name": "line1",
"meals": [
{
"name": "chicken2",
"isVegan": false
},
{
"name": "egges",
"isVegan": false
}
]
},
{
"name": "line2",
"meals": [
{
"name": "chicken",
"isVegan": true
},
{
"name": "egges",
"isVegan": true
}
]
}
]
}
Below is my expected output.
[Line {
name = line1;
meals = List<Meal> <0x281301b90> (
[0] Meal {
name = chicken2;
vegan = 0;
}
);
}]
You can retrieve a Meal object and show its parent object's name if you change the Meal class like this.
class Meal: Object {
#objc dynamic var name: String?
#objc dynamic var vegan: Bool = false
let lines = LinkingObjects(fromType: Line.self, property: "meals")
var line: Line { return lines.first! } // <- added
func initWithJSON(json: [String: Any]) {
self.name = json["name"] as? String
self.vegan = json["isVegan"] as! Bool
}
override static func primaryKey() -> String? {
return "name"
}
}
Instead of Line objects, retrieve Meal objects and access their parent object's name.
let meals = realm.objects(Meal.self).filter("name contains 'chicken2'")
for meal in meals {
print("name = \(meal.line.name!)")
print(meal)
}
Here is the output:
name = line1
Meal {
name = chicken2;
vegan = 0;
}
am unable to make nested dict, please help me out
{
"OneStopFlight" : "false",
"TokenId" : "86839fb9-ed93-46d3-b480-c58dbc441838",
"AdultCount" : "1",
"InfantCount" : "0",
"JourneyType" : "1",
"EndUserIp" : "192.168.10.10",
"DirectFlight" : "false",
"Segments" : [
{
"PreferredDepartureTime" : "2018-06-27T00:00:00",
"Origin" : "PNQ",
"EndUserIp" : "192.168.10.10",
"Destination" : "VNS",
"FlightCabinClass" : "1"
}
],
"ChildCount" : "0"
}
If you want to create such dictionary as did showed above , you can create it easily as below
let segmentDict : [[String:Any]] = [
[
"PreferredDepartureTime" : "2018-06-27T00:00:00",
"Origin" : "PNQ",
"EndUserIp" : "192.168.10.10",
"Destination" : "VNS",
"FlightCabinClass" : "1"
]
]
let paramDict : [String:Any] = [
"OneStopFlight" : "false",
"TokenId" : "86839fb9-ed93-46d3-b480-c58dbc441838",
"AdultCount" : "1",
"InfantCount" : "0",
"JourneyType" : "1",
"EndUserIp" : "192.168.10.10",
"DirectFlight" : "false",
"Segments" : segmentDict,
"ChildCount" : "0"
]
let segmentWithMultipleDict : [[String:Any]] = [
[
"PreferredDepartureTime" : "2018-06-27T00:00:00",
"Origin" : "PNQ",
"EndUserIp" : "192.168.10.10",
"Destination" : "VNS",
"FlightCabinClass" : "1"
],
[
"PreferredDepartureTime" : "2018-06-27T00:00:00",
"Origin" : "PNQ",
"EndUserIp" : "192.168.10.10",
"Destination" : "VNS",
"FlightCabinClass" : "1"
]
]
In case if you want to Deque such data
struct dequeResponse
{
var OneStopFlight : String = ""
var TokenId : String = ""
var AdultCount : String = ""
var InfantCount : String = ""
var JourneyType : String = ""
var EndUserIp : String = ""
var DirectFlight : String = ""
var Segments : [segment] = []
var ChildCount : String = ""
func getDataFromJSON(_ data: [String:Any]) -> dequeResponse{
var myResponseValues = dequeResponse()
if let value = data["OneStopFlight"] as? String {
myResponseValues.OneStopFlight = value
}
if let value = data["TokenId"] as? String {
myResponseValues.TokenId = value
}
if let value = data["AdultCount"] as? String {
myResponseValues.AdultCount = value
}
if let value = data["InfantCount"] as? String {
myResponseValues.InfantCount = value
}
if let value = data["JourneyType"] as? String {
myResponseValues.JourneyType = value
}
if let value = data["EndUserIp"] as? String {
myResponseValues.EndUserIp = value
}
if let value = data["DirectFlight"] as? String {
myResponseValues.DirectFlight = value
}
if let value = data["Segments"] as? [[String:Any]] {
let newSegment = segment()
myResponseValues.Segments = newSegment.getDataFromJSON(value)
}
if let value = data["ChildCount"] as? String {
myResponseValues.ChildCount = value
}
return myResponseValues
}
}
struct segment {
var PreferredDepartureTime : String?
var Origin : String?
var EndUserIp : String?
var Destination : String?
var FlightCabinClass : String?
func getDataFromJSON(_ data: [[String:Any]]) -> [segment] {
var segmentAray = [segment]()
for i in 0..<data.count {
var myCurrentSegment = segment()
if let value = data[i]["PreferredDepartureTime"] as? String {
myCurrentSegment.PreferredDepartureTime = value
}
if let value = data[i]["Origin"] as? String {
myCurrentSegment.Origin = value
}
if let value = data[i]["EndUserIp"] as? String {
myCurrentSegment.EndUserIp = value
}
if let value = data[i]["Destination"] as? String {
myCurrentSegment.Destination = value
}
if let value = data[i]["FlightCabinClass"] as? String {
myCurrentSegment.FlightCabinClass = value
}
segmentAray.append(myCurrentSegment)
}
return segmentAray
}
}
Usage
var jsonObject = dequeResponse()
jsonObject = jsonObject.getDataFromJSON(paramDict)
print(jsonObject.Segments)
Note If this doesn't meet your requirement please edit question with more detail
In my project, there is a bag object which was declared as static and when a customer click the "approve order" button, I serialize the bag object to JSON String. There is no problem so far. However, when I print the serialized json string, all of the "IDs" with Int in the bag converted to Bool type in json string result.
The related code blocks for this process as below:
This is my "Serialize" class:
public class Serializable : NSObject
{
func toDictionary() -> NSDictionary
{
var aClass : AnyClass? = self.dynamicType
var propertiesCount : CUnsignedInt = 0
var propertiesInAClass : UnsafeMutablePointer<objc_property_t> = class_copyPropertyList(aClass, &propertiesCount)
var propertiesDictionary : NSMutableDictionary = NSMutableDictionary()
for(var i = 0; i < Int(propertiesCount); i++)
{
var property = propertiesInAClass[i]
var propName = NSString(CString: property_getName(property), encoding: NSUTF8StringEncoding)
var propType = property_getAttributes(property)
var propValue : AnyObject! = self.valueForKey(propName!)
if(propValue is Serializable)
{
propertiesDictionary.setValue((propValue as Serializable).toDictionary(), forKey: propName!)
}
else if(propValue is Array<Serializable>)
{
var subArray = Array<NSDictionary>()
for item in (propValue as Array<Serializable>)
{
subArray.append(item.toDictionary())
}
propertiesDictionary.setValue(subArray, forKey: propName!)
}
else if(propValue is NSData)
{
propertiesDictionary.setValue((propValue as NSData).base64EncodedStringWithOptions(nil), forKey: propName!)
}
else if(propValue is Bool)
{
propertiesDictionary.setValue((propValue as Bool).boolValue, forKey: propName!)
}
else if(propValue is NSDate)
{
var date = propValue as NSDate
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "Z"
var dateString = NSString(format: "/Date(%.0f000%#)/", date.timeIntervalSince1970, dateFormatter.stringFromDate(date))
propertiesDictionary.setValue(dateString, forKey: propName!)
}
else
{
propertiesDictionary.setValue(propValue, forKey: propName!)
}
}
return propertiesDictionary
}
func toJson() -> NSData!
{
var dictionary = self.toDictionary()
var err: NSError?
return NSJSONSerialization.dataWithJSONObject(dictionary, options:NSJSONWritingOptions(0), error: &err)
}
func toJsonString() -> NSString!
{
return NSString(data: self.toJson(), encoding: NSUTF8StringEncoding)
}
override init()
{
}
}
This is my BagItem class:
class BagItem: Serializable, Hashable {
var uniqueID: Int = 0
override var hashValue: Int { return uniqueID.hashValue }
var bagItemId: String
var item: Item
var boughtDate: NSDate!
var boughtTime: String
var branch: Branch
var isMainItem: Bool
override init()
{
self.bagItemId = ""
self.item = Item()
self.boughtDate = NSDate()
self.boughtTime = ""
self.branch = Branch()
self.isMainItem = false
}
}
func ==(lhs: BagItem, rhs: BagItem) -> Bool
{
return lhs.uniqueID == rhs.uniqueID
}
This is my "SerializationBag" class:
class SerializableBag: Serializable
{
var bag: Array<BagItem> = []
override init()
{
}
}
This is my "ConvertBagToJSON" method in Bag class:
static func ConvertBagToJson() -> NSString
{
var serializer: SerializableBag = SerializableBag()
serializer.bag = self.bag
return serializer.toJsonString()
}
And my returned JSON String result as below:
{
"bag": [
{
"branch": {
"city": {
"cityId": false,
"cityName": ""
},
"town": {
"townName": "",
"townId": false
},
"branchName": "Branch",
"branchId": true,
"business": {
"businessPhotoPath": "",
"businessName": "",
"businessId": true
},
"branchAddress": "Some Address",
"branchTelephone": ""
},
"uniqueID": false,
"boughtDate": "/Date(1414581909000+0200)/",
"item": {
"itemName": "Pencil",
"itemId": true,
"itemPrice": true
},
"isMainItem": true,
"bagItemId": "9674D47B-0D2F-46CC-BA16-754875AE277D",
"hashValue": false,
"boughtTime": "00:30"
}
]
}
As you see, in JSON String, IDs are Bool, but they have to be in Int type. How can I solve this problem ?
Thank you for your answers
Best regards
This is because Int is bridged to NSNumber and NSNumber is always is Bool.
In your case, you don't need these lines:
else if(propValue is Bool)
{
propertiesDictionary.setValue((propValue as Bool).boolValue, forKey: propName!)
}
You can just delete them, because NSJSONSerialization can handle it.
let flg:NSNumber = true
let id:NSNumber = 1
let dict:NSDictionary = [
"bool": flg,
"id": id
]
let jsonDat = NSJSONSerialization.dataWithJSONObject(dict, options: .allZeros, error: nil)!
let jsonStr = NSString(data: dat, encoding:NSUTF8StringEncoding)
// -> {"id":1,"bool":true}
more relevant example:
class Foo:NSObject {
var flg:Bool = true
var id:Int = 1
}
let obj = Foo()
let dict:NSDictionary = [
"flg": obj.valueForKey("flg")!,
"id": obj.valueForKey("id")!
]
let jsonData = NSJSONSerialization.dataWithJSONObject(dict, options: .allZeros, error: nil)!
let jsonStr = NSString(data: jsonData, encoding:NSUTF8StringEncoding)!
// -> {"flg":true,"id":1}