how to use codable and decodable for the following json? - ios

I have a following sample json file I want to do it with modal classes but am not sure how to do this in code.
{
"countryCodes": [{
"country_code": "AF",
"country_name": "Afghanistan",
"dialling_code": "+93"
},
{
"country_code": "AL",
"country_name": "Albania",
"dialling_code": "+355"
},
{
"country_code": "DZ",
"country_name": "Algeria",
"dialling_code": "+213"
},
{
"country_code": "AS",
"country_name": "American Samoa",
"dialling_code": "+1"
}
]
}
My modal class is as follows
import Foundation
class CountryModal : NSObject, NSCoding{
var countryCodes : [CountryCode]!
/**
* Instantiate the instance using the passed dictionary values to set the properties values
*/
init(fromDictionary dictionary: [String:Any]){
countryCodes = [CountryCode]()
if let countryCodesArray = dictionary["countryCodes"] as? [[String:Any]]{
for dic in countryCodesArray{
let value = CountryCode(fromDictionary: dic)
countryCodes.append(value)
}
}
}
/**
* Returns all the available property values in the form of [String:Any] object where the key is the approperiate json key and the value is the value of the corresponding property
*/
func toDictionary() -> [String:Any]
{
var dictionary = [String:Any]()
if countryCodes != nil{
var dictionaryElements = [[String:Any]]()
for countryCodesElement in countryCodes {
dictionaryElements.append(countryCodesElement.toDictionary())
}
dictionary["countryCodes"] = dictionaryElements
}
return dictionary
}
/**
* NSCoding required initializer.
* Fills the data from the passed decoder
*/
#objc required init(coder aDecoder: NSCoder)
{
countryCodes = aDecoder.decodeObject(forKey: "countryCodes") as? [CountryCode]
}
/**
* NSCoding required method.
* Encodes mode properties into the decoder
*/
#objc func encode(with aCoder: NSCoder)
{
if countryCodes != nil{
aCoder.encode(countryCodes, forKey: "countryCodes")
}
}
}
and
import Foundation
class CountryCode : NSObject, NSCoding{
var countryCode : String!
var countryName : String!
var diallingCode : String!
/**
* Instantiate the instance using the passed dictionary values to set the properties values
*/
init(fromDictionary dictionary: [String:Any]){
countryCode = dictionary["country_code"] as? String
countryName = dictionary["country_name"] as? String
diallingCode = dictionary["dialling_code"] as? String
}
/**
* Returns all the available property values in the form of [String:Any] object where the key is the approperiate json key and the value is the value of the corresponding property
*/
func toDictionary() -> [String:Any]
{
var dictionary = [String:Any]()
if countryCode != nil{
dictionary["country_code"] = countryCode
}
if countryName != nil{
dictionary["country_name"] = countryName
}
if diallingCode != nil{
dictionary["dialling_code"] = diallingCode
}
return dictionary
}
/**
* NSCoding required initializer.
* Fills the data from the passed decoder
*/
#objc required init(coder aDecoder: NSCoder)
{
countryCode = aDecoder.decodeObject(forKey: "country_code") as? String
countryName = aDecoder.decodeObject(forKey: "country_name") as? String
diallingCode = aDecoder.decodeObject(forKey: "dialling_code") as? String
}
/**
* NSCoding required method.
* Encodes mode properties into the decoder
*/
#objc func encode(with aCoder: NSCoder)
{
if countryCode != nil{
aCoder.encode(countryCode, forKey: "country_code")
}
if countryName != nil{
aCoder.encode(countryName, forKey: "country_name")
}
if diallingCode != nil{
aCoder.encode(diallingCode, forKey: "dialling_code")
}
}
}
How do I use these models to get the value of to say India +91 code? I am new to swift so I am clueless as to how to use these models.
the method I know is simple method of ditionary
fileprivate func loadNames(Country: String ) {
// //var countryCodes : [CountryCode]!
// var dict = [Coordinator]?.self
if let filePath = Bundle.main.path(forResource: "CountryCode", ofType: "json") {
if let jsonData = NSData(contentsOfFile: filePath) {
do {
// countryCodes = try? JSONDecoder().decode(CountryCode.self, from: jsonData as Data)
var countryCodes = try JSONSerialization.jsonObject(with: jsonData as Data, options: []) as? [String: Any]
// let countryCodes = try? JSONDecoder().decode(Welcome.self, from: jsonData as Data)
print ("country d ",countryCodes!)
let countryArray = countryCodes!["countryCodes"] as? NSArray
if countryArray!.count > 0
{
for countryElement in countryArray!
{
let dict = countryElement as! NSDictionary
if (dict["country_code"] as! String).description == countryCodeLocale
{
print("found ",(dict["dialling_code"] as! String ).description)
country_codeText.text = (dict["dialling_code"] as! String ).description
phone_NumberText.text = "99133131602"
return
}
}
}
} catch {
print(error.localizedDescription)
}
}
}
}
func fetchValues()
{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Testing")
request.returnsObjectsAsFaults = false
do
{
let result = try context.fetch(request)
for data in result as! [NSManagedObject]
{
self.nameArr.append(data.value(forKey: "name") as! String)
self.lastNameArr.append(data.value(forKey: "lastname") as! String)
}
self.tableView.reloadData()
} catch {
print("Failed")
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.nameArr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? testTVCell
cell?.nameLbl.text = self.nameArr[indexPath.row]
cell?.lastNameLbl.text = self.lastNameArr[indexPath.row]
cell?.deleteBtn.tag = indexPath.row
return cell!
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
#IBAction func deleteAction(_ sender: UIButton) {
// self.nameArr.remove(at: sender.tag)
// self.lastNameArr.remove(at: sender.tag)
// self.tableView.reloadData()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Testing")
fetchRequest.returnsObjectsAsFaults = false
let index = sender.tag
do
{
if let result = try? context.fetch(fetchRequest)
{
for object in result as! [NSManagedObject]
{
print(object.value(forKey: "name") as! String)
if ((object).value(forKey: "name") as! String).description == nameArr[index]
{
print(object.value(forKey: "name") as! String)
context.delete(object )
self.lastNameArr.remove(at: index)
self.nameArr.remove(at: index)
DispatchQueue.main.async
{
self.tableView.reloadData()
}
break
}
}
}
}
catch
{
print("error")
}
let _ : NSError! = nil
do {
try context.save()
self.tableView.reloadData()
} catch {
print("error : \(error)")
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("Deleted")
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Testing")
fetchRequest.returnsObjectsAsFaults = false
let index = indexPath.row
do
{
if let result = try? context.fetch(fetchRequest)
{
for object in result as! [NSManagedObject]
{
print(object.value(forKey: "name") as! String)
if ((object).value(forKey: "name") as! String).description == nameArr[index]
{
print(object.value(forKey: "name") as! String)
context.delete(object )
DispatchQueue.main.async
{
}
}
}
}
}
catch
{
print("error")
}
let _ : NSError! = nil
do {
try context.save()
} catch {
print("error : \(error)")
}
self.lastNameArr.remove(at: index)
self.nameArr.remove(at: index)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
}
#IBAction func submitTapped(_ sender: Any)
{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Testing", in: context)
let newUser = NSManagedObject(entity: entity!, insertInto: context)
newUser.setValue(self.nameTxt.text, forKey: "name")
newUser.setValue(self.lastNameTxt.text, forKey: "lastname")
do
{
try context.save()
}
catch
{
print("Failed saving")
}
}
func apiCall()
{
let urlString = "https://example.org"
let url = NSURL(string: urlString)
let request = NSMutableURLRequest(url: url! as URL)
activityView.startAnimating()
self.view.addSubview(activityView)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request as URLRequest) { data,response,error in
if error != nil
{
DispatchQueue.main.async
{
let alert = UIAlertController(title: "Network Connection Lost", message: "Please try again", preferredStyle: .alert)
let ok = UIAlertAction(title: "OK", style: .cancel, handler: { Void in
self.activityView.stopAnimating()
})
alert.addAction(ok)
self.present(alert, animated: true, completion: nil)
}
return
}
do
{
let result = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as AnyObject
print(" JSON : ", result)
let a = result as! NSArray
let b = a[0] as! NSDictionary
print("name ", (b["Name"] as! String).description)
var nameArray = [String]()
for element in a
{
nameArray.append(((element as! NSDictionary)["Name"] as! String).description)
}
print("nameArray ", nameArray)
DispatchQueue.main.async
{
self.activityView.stopAnimating()
self.activityView.isHidden = true
}
}
catch
{
print("Error -> \(error)")
DispatchQueue.main.async
{
self.activityView.stopAnimating()
let alert = UIAlertController(title: "Alert?", message: error as? String,preferredStyle: .alert)
let ok = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alert.addAction(ok)
self.present(alert, animated: true, completion: nil)
return
}
}
}
task.resume()
}
}
let indexpath = NSIndexPath(row: sender.tag, section: 0)
let cell = tableView.cellForRow(at: indexpath as IndexPath) as? testTVCell
if (self.tableView.isEditing) {
cell?.deleteBtn.setTitle("Edit", for: .normal)
self.tableView.setEditing(false, animated: true)
} else {
cell?.deleteBtn.setTitle("Done", for: .normal)
self.tableView.setEditing(true, animated: true)
}
{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let urlString = appDelegate.serverUrl + "queryClassifiedList"
let url = NSURL(string: urlString)
let request = NSMutableURLRequest(url: url! as URL)
let spinner = JHSpinnerView.showDeterminiteSpinnerOnView(self.view)
spinner.progress = 0.0
self.view.addSubview(spinner)
request.httpMethod = "POST"
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")
var dict : [AnyHashable: Any] = [
"channel" : appDelegate.channel,
"device" : appDelegate.deviceId,
"classifiedtype" : self.classifiedType,
"startnum" : startNum,
"endnum" : endNum
]
if UserDefaults.standard.value(forKey: "categoryClassifiedFilter") as? Int != nil && UserDefaults.standard.value(forKey: "categoryClassifiedFilter") as? Int != -1
{
let categoryRow = (UserDefaults.standard.value(forKey: "categoryClassifiedFilter") as? Int)!
dict["categoryid"] = categoryRow
}
if UserDefaults.standard.value(forKey: "cityRowFilter") as? Int != nil && UserDefaults.standard.value(forKey: "cityRowFilter") as? Int != -1
{
let cityId = (UserDefaults.standard.value(forKey: "cityRowFilter") as? Int)!
dict["city"] = cityId
}
let jsonData: Data? = try? JSONSerialization.data(withJSONObject: dict, options: [])
request.httpBody = jsonData
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let urlString = appDelegate.serverUrl + "queryClassifiedList"
let url = NSURL(string: urlString)
let request = NSMutableURLRequest(url: url! as URL)
let spinner = JHSpinnerView.showDeterminiteSpinnerOnView(self.view)
spinner.progress = 0.0
self.view.addSubview(spinner)
request.httpMethod = "POST"
var bodyData : String!
bodyData = "channel=" + appDelegate.channel + "&device=" + appDelegate.deviceId + "&Classifiedtype=" + self.classifiedType.description + "&Startnum=" + startNum.description + "&Endnum=" + endNum.description
if UserDefaults.standard.value(forKey: "categoryClassifiedFilter") as? Int != nil && UserDefaults.standard.value(forKey: "categoryClassifiedFilter") as? Int != -1
{
let categoryRow = (UserDefaults.standard.value(forKey: "categoryClassifiedFilter") as? Int)!
bodyData = bodyData + "&Categoryid=" + categoryRow.description
}
if UserDefaults.standard.value(forKey: "cityRowFilter") as? Int != nil && UserDefaults.standard.value(forKey: "cityRowFilter") as? Int != -1
{
let cityId = (UserDefaults.standard.value(forKey: "cityRowFilter") as? Int)!
bodyData = bodyData + "&city=" + cityId.description
}
print("bodyData : ", bodyData)
request.httpBody = bodyData.data(using: String.Encoding.utf8)
}
but I want modal class method implementation. Can someone help?

You can try
struct Root: Codable {
let countryCodes: [CountryCode]
}
struct CountryCode: Codable {
let countryCode, countryName, diallingCode: String
enum CodingKeys: String, CodingKey {
case countryCode = "country_code"
case countryName = "country_name"
case diallingCode = "dialling_code"
}
}
let res = try? JSONDecoder().decode(Root.self,from:jsonData)
print(res.countryCodes)
res.countryCodes.forEach {
if $0.countryCode == "DZ" {
print($0.diallingCode)
}
}

Related

Segmented Control not performing accurately as expected

Using Segmented control with firebase is not selecting the accurate document when performing the action using the table cell button.
I am using segmented control with tableview in Swift IOS and Firestore database,
I am able to load the documents from database as per the segment control requirement. but when I tap on the button of the table cell it is processing action only on one document, not the accurate one, how should I ensure that table cell button process the document related to that particular id of the document only, below is the code I am sharing
class IPViewController: UIViewController {
#IBOutlet var segmentControl:UISegmentedControl!
#IBOutlet var tableView: UITableView!
var pendingPost:[Pending] = []
var completedPost:[Completed] = []
var postKey:String = ""
var db: Firestore!
var postAuthorId:String = ""
var postAuthorname:String = ""
var PostTitle:String = ""
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
// Do any additional setup after loading the view.
retrieveAllPosts()
}
func retrieveAllPosts(){
let postsRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("Detaling2").limit(to: 50)
postsRef.addSnapshotListener { (snapshot, error) in
if let error = error {
print(error.localizedDescription)
} else {
if let snapshot = snapshot {
for document in snapshot.documents {
let data = document.data()
let username = data["post_author_username"] as? String ?? ""
let postTitle = data["postTitle"] as? String ?? ""
let newSourse = Pending(_documentId: document.documentID, _username: username, _postTitle: postTitle, _postcategory: postcategory)
self.pendingPost.append(newSourse)
}
self.tableView.reloadData()
}
}
}
}
func retrieveAllPosts2(){
let postsRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("Detailing1").limit(to: 50)
postsRef.addSnapshotListener { (snapshot, error) in
if let error = error {
print(error.localizedDescription)
} else {
if let snapshot = snapshot {
for document in snapshot.documents {
let data = document.data()
//self.postKey = document.documentID
let username = data["post_author_username"] as? String ?? ""
let postTitle = data["postTitle"] as? String ?? ""
let newSourse1 = Completed(_documentId: document.documentID, _username: username, _postTitle: postTitle)
self.completedPost.append(newSourse1)
}
self.tableView.reloadData()
}
}
}
}
#IBAction func indexChanged(_ sender: UISegmentedControl) {
switch segmentControl.selectedSegmentIndex
{
case 0:
self.pendingPost.removeAll()
retrieveAllPosts()
case 1:
self.completedPost.removeAll()
retrieveAllPosts2()
default:
break
}
//self.tableView.reloadData()
}
#objc func toComments(_ sender: AnyObject) {
let commentbutton = sender as! UIButton
let post = pendingPost[commentbutton.tag]
postKey = post._documentId // or what key value it is
print("hello")
performSegue(withIdentifier: "IPtoComments", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var vc = segue.destination as! CommentListViewController
vc.postId = postKey
}
#objc func favupdate(_ sender: AnyObject) {
let commentbutton = sender as! UIButton
let post = pendingPost[commentbutton.tag]
postKey = post._documentId // or what key value it is
//print(postKey + "hello777777")
let userMarkRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("marked_posts").document(postKey)
let postRef = Firestore.firestore().collection("posts").document(postKey)
postRef.getDocument{(document, error) in
if let document = document, document.exists{
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
self.postAuthorId = document.get("post_author_id") as! String
self.postAuthorname = document.get("post_author_username") as! String
self.PostTitle = document.get("postTitle") as! String
self.postContent = document.get("postContent") as! String
self.postAuthorEmail = document.get("post_author_email") as! String
self.postCategory = document.get("postcategory") as! String
self.postAuthorfullname = document.get("post_author_fullname") as! String
self.postAuthorGender = document.get("post_author_gender") as! String
self.postAuthorPicUrl = document.get("post_user_profile_pic_url") as! String
// let l11:Bool = document.get("l1") as! Bool
// self.postTimeStamp = document.get("post_timeStamp") as! String
self.postAuthorSpinnerC = document.get("post_author_spinnerC") as! String
}
let postObject = [
"post_author_id": self.postAuthorId,
"post_author_username": self.postAuthorname,
"postTitle": self.PostTitle
] as [String : Any]
userMarkRef.setData(postObject, merge: true) { (err) in
if let err = err {
print(err.localizedDescription)
}
print("Successfully set new user data")
}
}
}
#objc func favupdate1(_ sender: AnyObject) {
let commentbutton = sender as! UIButton
let post = completedPost[commentbutton.tag]
postKey = post._documentId
let userMarkRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("details1").document(postKey)
let postRef = Firestore.firestore().collection("posts").document(postKey)
postRef.getDocument{(document, error) in
if let document = document, document.exists{
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
self.postAuthorId = document.get("post_author_id") as! String
self.postAuthorname = document.get("post_author_username") as! String
self.PostTitle = document.get("postTitle") as! String
}
let postObject = [
"post_author_id": self.postAuthorId,
"post_author_username": self.postAuthorname,
"postTitle": self.PostTitle
] as [String : Any]
userMarkRef.setData(postObject, merge: true) { (err) in
if let err = err {
print(err.localizedDescription)
}
print("Successfully set new user data")
}
}
}
}
extension IPViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var value = 0
switch segmentControl.selectedSegmentIndex{
case 0:
value = pendingPost.count
break
case 1:
value = completedPost.count
break
default:
break
}
return value
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ipwcell", for: indexPath) as! IPWCELL
switch segmentControl.selectedSegmentIndex{
case 0:
cell.pending1 = pendingPost[indexPath.row]
cell.commentbuttonIp.tag = indexPath.row
cell.commentbuttonIp.addTarget(self, action: #selector(toComments(_:)), for: .touchUpInside)
cell.favoritebutton1.addTarget(self, action: #selector(favupdate(_:)), for: .touchUpInside)
break
case 1:
cell.completed1 = completedPost[indexPath.row]
cell.commentbuttonIp.tag = indexPath.row
cell.commentbuttonIp.addTarget(self, action: #selector(toComments(_:)), for: .touchUpInside)
cell.favoritebutton1.addTarget(self, action: #selector(favupdate1(_:)), for: .touchUpInside)
break
default:
break
}
return cell
}
}
#objc func favupdate(_ sender: AnyObject) {
if segmentView.selectedSegmentIndex == 0 {
let commentbutton = sender as! UIButton
let post = pendingPost[commentbutton.tag]
postKey = post._documentId // or what key value it is
//print(postKey + "hello777777")
let userMarkRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("marked_posts").document(postKey)
let postRef = Firestore.firestore().collection("posts").document(postKey)
postRef.getDocument{(document, error) in
if let document = document, document.exists{
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
self.postAuthorId = document.get("post_author_id") as! String
self.postAuthorname = document.get("post_author_username") as! String
self.PostTitle = document.get("postTitle") as! String
self.postContent = document.get("postContent") as! String
self.postAuthorEmail = document.get("post_author_email") as! String
self.postCategory = document.get("postcategory") as! String
self.postAuthorfullname = document.get("post_author_fullname") as! String
self.postAuthorGender = document.get("post_author_gender") as! String
self.postAuthorPicUrl = document.get("post_user_profile_pic_url") as! String
// let l11:Bool = document.get("l1") as! Bool
// self.postTimeStamp = document.get("post_timeStamp") as! String
self.postAuthorSpinnerC = document.get("post_author_spinnerC") as! String
}
let postObject = [
"post_author_id": self.postAuthorId,
"post_author_username": self.postAuthorname,
"postTitle": self.PostTitle
] as [String : Any]
userMarkRef.setData(postObject, merge: true) { (err) in
if let err = err {
print(err.localizedDescription)
}
print("Successfully set new user data")
}
}
}else {
let commentbutton = sender as! UIButton
let post = completedPost[commentbutton.tag]
postKey = post._documentId
let userMarkRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("details1").document(postKey)
let postRef = Firestore.firestore().collection("posts").document(postKey)
postRef.getDocument{(document, error) in
if let document = document, document.exists{
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
self.postAuthorId = document.get("post_author_id") as! String
self.postAuthorname = document.get("post_author_username") as! String
self.PostTitle = document.get("postTitle") as! String
}
let postObject = [
"post_author_id": self.postAuthorId,
"post_author_username": self.postAuthorname,
"postTitle": self.PostTitle
] as [String : Any]
userMarkRef.setData(postObject, merge: true) { (err) in
if let err = err {
print(err.localizedDescription)
}
print("Successfully set new user data")
}
}
}
}
#objc func toComments(_ sender: AnyObject) {
if segmentView.selectedSegmentIndex == 0 {
let commentbutton = sender as! UIButton
let post = pendingPost[commentbutton.tag]
postKey = post._documentId // or what key value it is
print("hello")
performSegue(withIdentifier: "IPtoComments", sender: self)
}else {
let commentbutton = sender as! UIButton
let post = pendingPost[commentbutton.tag]
postKey = post._documentId // or what key value it is
print("hello")
performSegue(withIdentifier: "IPtoComments", sender: self)
}
}

How to Display Data From Api and Json.file

I have two data's
1. From json
2. From json.file
Tha data format is below:-
{
"data": [
{
"question": "Gender",
"options": [
"Male",
"Female"
],
"button_type": "2"
},
{
"question": "How old are you",
"options": [
"Under 18",
"Age 18 to 24",
"Age 25 to 40",
"Age 41 to 60",
"Above 60"
],
"button_type": "2"
},
{
"button_type": "2",
"question": "I am filling the Questionnaire for?",
"options": [
"Myself",
"Mychild",
"Partner",
"Others"
]
}
]
}
This is my model:-
enum NHAnswerType:Int
{
case NHAnswerCheckboxButton = 1
case NHAnswerRadioButton
case NHAnswerSmileyButton
case NHAnswerStarRatingButton
case NHAnswerTextButton
}
class NH_QuestionListModel: NSObject {
var dataListArray33:[NH_OptionsModel] = []
var id:Int!
var question:String!
var buttontype:String!
var options:[String]?
var v:String?
var answerType:NHAnswerType?
var optionsModelArray:[NH_OptionsModel] = []
init(dictionary :JSONDictionary) {
guard let question = dictionary["question"] as? String,
let typebutton = dictionary["button_type"] as? String,
let id = dictionary["id"] as? Int
else {
return
}
// (myString as NSString).integerValue
self.answerType = NHAnswerType(rawValue: Int(typebutton)!)
if let options = dictionary["options"] as? [String]{
print(options)
for values in options{
print(values)
let optionmodel = NH_OptionsModel(values: values)
self.optionsModelArray.append(optionmodel)
}
}
self.buttontype = typebutton
self.question = question
self.id = id
}
}
optionmodel:-
class NH_OptionsModel: NSObject {
var isSelected:Bool? = false
var textIndexPath :IndexPath?
var dummyisSelected:Bool? = false
var v:String?
var values:String?
init(values:String) {
self.values = values
print( self.values)
}
}
Viewmodel in questionviewmodel:-
func loadData(completion :#escaping (_ isSucess:Bool) -> ()){
loadFromWebserviceData { (newDataSourceModel) in
if(newDataSourceModel != nil)
{
self.datasourceModel = newDataSourceModel!
completion(true)
}
else{
completion(false)
}
}
}
func loadFromWebserviceData(completion :#escaping (NH_QuestionDataSourceModel?) -> ()){
//with using Alamofire ..............
// http://localhost/json_data/vendorlist.php
Alamofire.request("http://www.example.com").validate(statusCode: 200..<300).validate(contentType: ["application/json"]).responseJSON{ response in
let status = response.response?.statusCode
print("STATUS \(status)")
print(response)
switch response.result{
case .success(let data):
print("success",data)
let result = response.result
print(result)
if let wholedata = result.value as? [String:Any]{
print(wholedata)
// let data2 = wholedata["data"] as? [String:Any]
self.datasection1 = wholedata
if let data1 = wholedata["data"] as? Array<[String:Any]>{
print(data)
print(response)
for question in data1 {
let typebutton = question["button_type"] as? String
print(typebutton)
self.type = typebutton
let options = question["options"] as! [String]
// self.dataListArray1 = [options]
self.tableArray.append(options)
// self.savedataforoptions(completion: <#T##(NH_OptionslistDataSourceModel?) -> ()#>)
self.no = options.count
}
print(self.tableArray)
let newDataSource:NH_QuestionDataSourceModel = NH_QuestionDataSourceModel(array: data1)
completion(newDataSource)
}
}
case .failure(let encodingError ):
print(encodingError)
// if response.response?.statusCode == 404{
print(encodingError.localizedDescription)
completion(nil)
}
}}
dummy data viewmodel:-
func loadFromDummyData(completion :#escaping (NH_DummyDataSourceModel?) -> ()){
if let path = Bundle.main.path(forResource: "jsonData", ofType: "json") {
do {
let jsonData = try NSData(contentsOfFile: path, options: NSData.ReadingOptions.mappedIfSafe)
do {
let jsonResult: NSDictionary = try JSONSerialization.jsonObject(with: jsonData as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
// self.datasection2 = jsonResult as! [String : Any]
let people1 = jsonResult["data"] as? [String:Any]
self.datasection2 = jsonResult as! [String : Any]
if let people = jsonResult["data"] as? Array<[String:Any]> {
// self.dict = people
for person in people {
let options = person["options"] as! [String]
self.tableArray.append(options)
let name = person ["question"] as! String
self.tableArray.append(options)
}
let newDataSource:NH_DummyDataSourceModel = NH_DummyDataSourceModel(array: people)
completion(newDataSource)
}
} catch {}
} catch {}
}
}
func loadData1(completion :#escaping (_ isSucess:Bool) -> ()){
loadFromDummyData{ (newDataSourceModel) in
if(newDataSourceModel != nil)
{
self.datasourceModel = newDataSourceModel!
completion(true)
}
else{
completion(false)
}
}
}
finally in the viewcontroller:-
in viewDidLoad:-
questionViewModel.loadData { (isSuccess) in
if(isSuccess == true)
{
let sec = self.questionViewModel.numberOfSections()
for _ in 0..<sec
{
self.questionViewModel.answers1.add("")
self.questionViewModel.questions1.add("")
self.questionViewModel.questionlist1.add("")
}
self.item1 = [self.questionViewModel.datasection1]
self.activityindicator.stopAnimating()
self.activityindicator.isHidden = true
self.tableview.refreshControl = refreshControl
self.tableview .allowsMultipleSelection = false
self.tableview.reloadData()
self.dummyDataViewModel.loadData1{ (isSuccess) in
if(isSuccess == true)
{
}
else{
self.viewDidLoad()
}
}
}
else{
self.activityindicator.stopAnimating()
self.activityindicator.isHidden = true
let controller = UIAlertController(title: "No Internet Detected", message: "This app requires an Internet connection", preferredStyle: .alert)
// Create the actions
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
NSLog("OK Pressed")
self.viewDidLoad()
}
controller.addAction(okAction)
self.present(controller, animated: true, completion: nil)
}
self.sections = [Category(name:"A",items:self.item1),
Category(name:"B",items:self.item2),
]
print(self.sections)
self.tableview.reloadData()
}
This is the format from json.file and also from the api.
I have used tableview.
So i need to list the header title from the key "question"
And the cell for row should display from the option keys.
So how to add this two data from the Json and Json.file?
You can create your models which represents your model. Preferably like
struct ResponseModel: Codable {
var data: [Question]?
}
struct QuestionModel{
var question: String?
var options: [String]?
}
Then after your Ajax post use
let responseData = try JSONDecoder().decode(AjaxResponse<ResponseModel>.self, from: data!)
Now you have your data.
You can then do in your UITableViewDeleates
//number of sections
resposnseData.data.count
//number of rows in section
responseData.data[section].options.count
//cell for index modify your cell using
response.data[indexPath.section].options[indexPath.row]
Hope it helps.

How to write model class for json data with dictionary?

In this class already i had written model class but here some of the data has been added newly but i am trying to create for the model class for remaining dictionaries but unable to implement it can anyone help me how to implement it ?
In this already i had implemented model class for items array and here i need to create a model class for search criteria dictionary and inside arrays
func listCategoryDownloadJsonWithURL() {
let url = URL(string: listPageUrl)!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil { print(error!); return }
do {
if let jsonObj = try JSONSerialization.jsonObject(with: data!) as? [String:Any] {
let objArr = jsonObj["items"] as? [[String:Any]]
self.list = objArr!.map{List(dict: $0)}
DispatchQueue.main.async {
let itemsCount = self.list.count
for i in 0..<itemsCount {
let customAttribute = self.list[i].customAttribute
for j in 0..<customAttribute.count {
if customAttribute[j].attributeCode == "image" {
let baseUrl = "http://192.168.1.11/magento2/pub/media/catalog/product"
self.listCategoryImageArray.append(baseUrl + customAttribute[j].value)
}
}
}
self.activityIndicator.stopAnimating()
self.activityIndicator.hidesWhenStopped = true
self.collectionView.reloadData()
self.collectionView.isHidden = false
self.tableView.reloadData()
}
}
} catch {
print(error)
}
}
task.resume()
}
struct List {
let name : String
let sku : Any
let id : Int
let attributeSetId : Int
let price : Int
let status : Int
let visibility : Int
let typeId: String
let createdAt : Any
let updatedAt : Any
var customAttribute = [ListAttribute]()
init(dict : [String:Any]) {
if let customAttribute = dict["custom_attributes"] as? [[String: AnyObject]] {
var result = [ListAttribute]()
for obj in customAttribute {
result.append(ListAttribute(json: obj as! [String : String])!)
}
self.customAttribute = result
} else {
self.customAttribute = [ListAttribute]()
}
self.name = (dict["name"] as? String)!
self.sku = dict["sku"]!
self.id = (dict["id"] as? Int)!
self.attributeSetId = (dict["attribute_set_id"] as? Int)!
self.price = (dict["price"] as? Int)!
self.status = (dict["status"] as? Int)!
self.visibility = (dict["visibility"] as? Int)!
self.typeId = (dict["type_id"] as? String)!
self.createdAt = dict["created_at"]!
self.updatedAt = dict["updated_at"]!
}
}
struct ListAttribute {
let attributeCode : String
let value : String
init?(json : [String:String]) {
self.attributeCode = (json["attribute_code"])!
self.value = (json["value"])!
}
}

I am unable to get the child names from given url in swift 3?

In the api am getting global array but in this I am unable to get the children names as separate array only the last loaded array name has been getting in the array how to get the all children names in the array please help me how to get all the names in it and here is my code already tried
var detailsArray = NSArray()
var globalArray = NSMutableArray()
let url = "http://www.json-generator.com/api/json/get/cwqUAMjKGa?indent=2"
func downloadJsonWithURL() {
let url = NSURL(string: self.url)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
{
self.detailsArray = (jsonObj?.value(forKey: "data") as? [[String: AnyObject]])! as NSArray
print(self.detailsArray)
for item in self.detailsArray
{
let majorDic = NSMutableDictionary()
let detailDict = item as! NSDictionary
print(detailDict["name"]!)
majorDic .setValue(detailDict["name"]!, forKey: "name")
print(detailDict["children"]!)
if !(detailDict["children"]! is NSNull)
{
let children = detailDict["children"]! as! NSArray
let childrenstring = NSMutableString()
if children.count > 0 {
for item in children{
let chilDic = item as! NSDictionary
print(chilDic["name"]!)
print(chilDic["products"]!)
majorDic.setValue(chilDic["name"]!, forKey: "Childernname")
let products = chilDic["products"]! as! NSArray
if products.count > 0
{
for item in products
{
var sr = String()
sr = (item as AnyObject) .value(forKey: "name") as! String
childrenstring.append(sr)
childrenstring.append("*")
}
majorDic.setValue(childrenstring, forKey: "Childernproducts")
}
else
{
print("products.count\(products.count)")
majorDic.setValue("NO DATA", forKey: "Childernproducts")
}
}
}
else
{
print("childernw.count\(children.count)")
majorDic.setValue("NO DATA", forKey: "Childernname")
}
}
else
{
majorDic.setValue("NO DATA", forKey: "Childernname")
majorDic.setValue("NO DATA", forKey: "Childernproducts")
}
self.globalArray.add(majorDic)
}
print("TOTAL ASSECTS\(self.globalArray)")
OperationQueue.main.addOperation({
self.tableView.reloadData()
print(self.globalArray)
print(self.detailsArray)
})
}
}).resume()
}
Try this:
var detailsArray = [DataList]()
func downloadJsonWithURL() {
let url = NSURL(string: "http://www.json-generator.com/api/json/get/cwqUAMjKGa?indent=2")
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
{
let objArr = (jsonObj?["data"] as? [[String: AnyObject]])! as NSArray
for obj in objArr {
self.detailsArray.append(DataList(json: obj as! [String : AnyObject]))
}
print(self.detailsArray)
}
}).resume()
}
Model Class
class DataList: NSObject {
var count: Int
var category_id: Int
var childern:[Children]
var name:String
init (json: [String: AnyObject]){
if let childrenList = json["children"] as? [[String: AnyObject]] {
var result = [Children]()
for obj in childrenList {
result.append(Children(json: obj))
}
self.childern = result
} else {
self.childern = [Children]()
}
if let count = json["count"] as? Int { self.count = count }
else { self.count = 0 }
if let category_id = json["category_id"] as? Int { self.category_id = category_id }
else { self.category_id = 0 }
if let name = json["name"] as? String { self.name = name }
else { self.name = "" }
}
}
class Children:NSObject{
var count:Int
var category_id:Int
var products:[Products]
var name:String
init (json: [String: AnyObject]){
if let productList = json["products"] as? [[String: AnyObject]] {
var result = [Products]()
for obj in productList {
result.append(Products(json: obj))
}
self.products = result
} else {
self.products = [Products]()
}
if let count = json["count"] as? Int { self.count = count }
else { self.count = 0 }
if let category_id = json["category_id"] as? Int { self.category_id = category_id }
else { self.category_id = 0 }
if let name = json["name"] as? String { self.name = name }
else { self.name = "" }
}
}
class Products:NSObject{
var product_id:Int
var name:String
init (json: [String: AnyObject]){
if let product_id = json["product_id"] as? Int { self.product_id = product_id }
else { self.product_id = 0 }
if let name = json["name"] as? String { self.name = name }
else { self.name = "" }
}
}
NOTE: Please check your data type while parsing
I too had the same problem. Instead of using for loop try using flatMap() and then extract the value using value(forKey: " ") function
let productNames = productValues.flatMap() {$0.value}
let names = (productNames as AnyObject).value(forKey: "name")
It had worked for me for my json. My Json was similar to yours.
I got separate values in array.

Access JSON array inside another array

So far I only had to deal with simple JSON arrays with only a single array. I have now combined 2 arrays together so I can get my user data and all the reviews for that user:
[
{
"user_id": "16",
"name": "Jonh",
"lastName": "appleseed",
"username": "jonh#me.com",
"sex": "male",
"image_url": "",
"review": [
{
"reviewID": "4",
"merchant_id": "17",
"rating": "5",
"user_id": "16",
"comments": "Very good customer. Strongly suggested",
"date": "0000-00-00",
"reviewYear": "",
"publish": "1"
},
{
"reviewID": "8",
"merchant_id": "16",
"rating": "2",
"user_id": "16",
"comments": "Automatic review due to "NO SHOW" without informing the merchant",
"date": "0000-00-00",
"reviewYear": "",
"publish": "1"
}
]
}
]
before I added the reviews my model looked like this:
import Foundation
class Users {
let userImage:String?
let name:String?
let sex:String?
let image_url:String?
init(dictionary:NSDictionary) {
userImage = dictionary["userImage"] as? String
name = dictionary["name"] as? String
sex = dictionary["sex"] as? String
image_url = dictionary["image_url"] as? String
}
}
func loadUser(completion:(([Users])-> Void), userId: String){
let myUrl = NSURL(string: "http://www.myWebSite.com/api/v1.0/users.php")
let request = NSMutableURLRequest(URL: myUrl!)
request.HTTPMethod = "POST"
let postString = "user_id=\(userId)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{ data, response, error in
if error != nil {
print("error\(error)")
} else {
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! NSArray
print(json)
var users = [Users]()
for user in json{
let user = Users(dictionary: user as! NSDictionary)
users.append(user)
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0 )){
dispatch_async(dispatch_get_main_queue()){
completion(users)
}
}
}
} catch{
}
}
}
task.resume()
}
which I could then used in my viewController:
func loadModel() {
let loadingNotification = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
loadingNotification.mode = MBProgressHUDMode.Indeterminate
loadingNotification.labelText = "updating your deals..."
users = [Users]()
let api = Api()
api.loadUser(didLoadUsers , userId: "16")
}
func didLoadUsers(users:[Users]){
self.users = users
self.tableView.reloadData()
MBProgressHUD.hideAllHUDsForView(self.view, animated: true)
}
Can I get the review field so I can present it in a table view controller?
I added to your Users class an array of reviews that will be populated in your user init() method. I recommend you to take look at struct Review and make your user class a struct, and change your NSDictionary to swift Dictionary.
struct Review {
let reviewID:String?
let merchant_id:String?
let user_id:String?
//to be continued with your own implementation...
init(dictionary:[String:String]) {
reviewID = dictionary["reviewID"]
merchant_id = dictionary["merchant_id"]
user_id = dictionary["user_id"]
//to be continued with your own implementation...
}
}
class Users {
let userImage:String?
let name:String?
let sex:String?
let image_url:String?
var reviews:[Review]
init(dictionary:[String:AnyObject]) {
userImage = dictionary["userImage"] as? String
name = dictionary["name"] as? String
sex = dictionary["sex"] as? String
image_url = dictionary["image_url"] as? String
reviews = [Review]()
if let userReviews = dictionary["review"] as? [[String:AnyObject]] {
for review in userReviews {
if let unwrapedReview = review as? [String:String] {
let r = Review(dictionary: unwrapedReview)
reviews.append(r)
}
}
}
}
}
Also I recommend you in the future to use SwiftyJSON for parsing JSON and also Alamofire for networking requests.
Done. It was easier than what I thought. I just had to add a UserReview class and change the signature of loadUser function:
func loadUser(completion:((user: [Users], review: [UserReview])-> Void), userId: String){
let myUrl = NSURL(string: "http://www.myWebsite.com/api/v1.0/users.php")
let request = NSMutableURLRequest(URL: myUrl!)
request.HTTPMethod = "POST"
let postString = "user_id=\(userId)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{ data, response, error in
if error != nil {
print("error\(error)")
}else{
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! NSArray
var users = [Users]()
for user in json{
let user = Users(dictionary: user as! NSDictionary as! [String : AnyObject])
users.append(user)
//*********** now I can access the reviews from my son***************
let reviewArray = json[0]["review"] as! NSArray
var reviews = [UserReview]()
for review in reviewArray{
let review = UserReview(dictionary: review as! NSDictionary as! [String : AnyObject])
reviews.append(review)
}
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0 )){
dispatch_async(dispatch_get_main_queue()){
completion(user: users, review: reviews)
}
}
}
} catch{
}
}
}
task.resume()
}
So I can use it in my tableViewController
var users: [Users]?
var reviews: [UserReview]?
func loadModel() {
let loadingNotification = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
loadingNotification.mode = MBProgressHUDMode.Indeterminate
loadingNotification.labelText = "updating..."
users = [Users]()
reviews = [UserReview]()
let api = Api()
api.loadUser(didLoadUsers , userId: "16")
}
func didLoadUsers(users:[Users], reviews:[UserReview] ){
self.users = users
self.reviews = reviews
self.tableView.reloadData()
MBProgressHUD.hideAllHUDsForView(self.view, animated: true)
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return users!.count
}
if section == 1 {
return 1
}
if section == 2 {
return reviews!.count
}
return 0
}
So in my cellForRowAtIndexPath I can now load all the reviews
if indexPath.section == 2 {
let review = reviews![indexPath.row]
let reviewCell = tableView.dequeueReusableCellWithIdentifier("reviewCell", forIndexPath: indexPath) as! UserReviewsTableViewCell
reviewCell.useReview(review)
return reviewCell
}

Resources