Firebase Database indexPath - ios

I'm trying to retrieve data from firebase using this function but I'm not getting all the data:
func retrieveVideos(_ completionBlock: #escaping (_ success: Bool, _ error: Error?) -> ()) {
let userMessagesRef = DataService.instance.REF_ARTISTARTS.child(Auth.auth().currentUser!.uid)
userMessagesRef.observe(.childAdded, with: { [weak self] (snapshot) in
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
print("SNAPSHOT: (snapshot.count)") = 12
}
guard let strongSelf = self else {return}
guard let dictionary = snapshot.value as? [String: AnyObject] else {
completionBlock(false, nil)
return
}
var arts = [Art?]()
if let art = ArtViewModelController.parse(dictionary) {
arts.append(art)
print(arts.count) = 1
}
strongSelf.viewModels = ArtViewModelController.initViewModels(arts)
completionBlock(true, nil)
}) { (error: Error) in
completionBlock(false, error)
}
}
var viewModelsCount: Int {
return viewModels.count
}
func viewModel(at index: Int) -> ArtViewModel? {
guard index <= 0 && index < viewModelsCount else { return nil }
return viewModels[index]
}
}
private extension ArtViewModelController {
static func parse(_ dictionary: [String: Any]) -> Art? {
let artID = dictionary["artID"] as? String ?? ""
let imgUrl = dictionary["imageUrl"] as? String ?? ""
let title = dictionary["title"] as? String ?? ""
let description = dictionary["description"] as? String ?? ""
let price = dictionary["price"] as? NSNumber ?? 0
let type = dictionary["type"] as? String ?? ""
let height = dictionary["height"] as? NSNumber ?? 0
let width = dictionary["width"] as? NSNumber ?? 0
let postDate = dictionary["postDate"] as? NSNumber ?? 0
return Art(artID: artID, imgUrl: imgUrl, price: price, title: title, description: description, type: type, height: height, width: width, postDate: postDate)
}
static func initViewModels(_ arts: [Art?]) -> [ArtViewModel?] {
print("SECOND VIDEO COUNT: \(arts.count)")
return arts.map { art in
if let art = art {
return ArtViewModel(art: art)
} else {
return nil
}
}
}
}
My problem is that my index.count is always equal to 1 but it's supposed to equal to 12.
Here's the original code:
func retrieveUsers(_ completionBlock: #escaping (_ success: Bool, _ error: NSError?) -> ()) {
let urlString = "http://localhost:3000/users"
let session = URLSession.shared
guard let url = URL(string: urlString) else {
completionBlock(false, nil)
return
}
let task = session.dataTask(with: url) { [weak self] (data, response, error) in
guard let strongSelf = self else { return }
guard let data = data else {
completionBlock(false, error as NSError?)
return
}
let error = NSError.createError(0, description: "JSON parsing error")
if let jsonData = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: AnyObject]] {
guard let jsonData = jsonData else {
completionBlock(false, error)
return
}
var users = [User?]()
for json in jsonData {
if let user = UserViewModelController.parse(json) {
users.append(user)
}
}
strongSelf.viewModels = UserViewModelController.initViewModels(users)
completionBlock(true, nil)
} else {
completionBlock(false, error)
}
}
task.resume()
}
So I'm trying to do the same thing but with Firebase. If you need more details please just ask!
SNAPSHOT PRINT:
SNAPSHOT: Optional({
description = "Yes ";
height = 87;
imageUrl = "https://firebasestorage.googleapis.com/v0/b/medici-b6f69.appspot.com/o/Art%2F4bjurh5FFNOUb2D4oHGfRqEm7Il2%2FB6E2A9F0-C409-4732-B6D9-14382E6796F5?alt=media&token=32992b9c-4a08-456d-8950-119f681b4cdc";
postDate = 1498921599547;
price = 23;
private = 0;
title = "Yes ";
type = Modern;
userUID = 4bjurh5FFNOUb2D4oHGfRqEm7Il2;
width = 71;
})
SNAPSHOT: Optional({
artHeight = 85;
artWidth = 123;
description = "Yes ";
height = 85;
imageUrl = "https://firebasestorage.googleapis.com/v0/b/medici-b6f69.appspot.com/o/Art%2F4bjurh5FFNOUb2D4oHGfRqEm7Il2%2F16280189-5AEA-47CB-9251-C95635FFE56C?alt=media&token=8198df4e-da8c-4883-b278-fc7c14730f69";
postDate = 1498921623601;
price = 23;
private = 0;
title = "blacks don\U2019t Crack ";
type = Abstract;
userUID = 4bjurh5FFNOUb2D4oHGfRqEm7Il2;
width = 123;
})
SNAPSHOT: Optional({
artHeight = 81;
artWidth = 11;
description = "Yes ";
height = 81;
imageUrl = "https://firebasestorage.googleapis.com/v0/b/medici-b6f69.appspot.com/o/Art%2F4bjurh5FFNOUb2D4oHGfRqEm7Il2%2F305FDE5C-1C5C-4ABD-B4A1-4FA224421202?alt=media&token=fcba57df-e252-47c2-be92-7836bd97e6fe";
postDate = 1502242913081;
price = 23;
private = 0;
title = "Title ";
type = type;
userUID = 4bjurh5FFNOUb2D4oHGfRqEm7Il2;
width = 118;
})
SNAPSHOT: Optional({
description = "Hey ";
height = 82;
imageUrl = "https://firebasestorage.googleapis.com/v0/b/medici-b6f69.appspot.com/o/Art%2F4bjurh5FFNOUb2D4oHGfRqEm7Il2%2F04B00727-2AE4-41E3-BCA3-3980182C7F67?alt=media&token=cc1d6a92-1625-453c-bf1f-2ec84d6df51a";
postDate = 1503341277594;
price = 23;
private = 0;
title = "Title ";
type = Modern;
userUID = 4bjurh5FFNOUb2D4oHGfRqEm7Il2;
width = 124;
})
DIC: ["height": 87, "private": 0, "width": 71, "postDate": 1498921599547, "description": Yes , "title": Yes , "imageUrl": https://firebasestorage.googleapis.com/v0/b/medici-b6f69.appspot.com/o/Art%2F4bjurh5FFNOUb2D4oHGfRqEm7Il2%2FB6E2A9F0-C409-4732-B6D9-14382E6796F5?alt=media&token=32992b9c-4a08-456d-8950-119f681b4cdc, "userUID": 4bjurh5FFNOUb2D4oHGfRqEm7Il2, "price": 23, "type": Modern]
DIC: ["artWidth": 123, "height": 85, "private": 0, "artHeight": 85, "description": Yes , "postDate": 1498921623601, "width": 123, "imageUrl": https://firebasestorage.googleapis.com/v0/b/medici-b6f69.appspot.com/o/Art%2F4bjurh5FFNOUb2D4oHGfRqEm7Il2%2F16280189-5AEA-47CB-9251-C95635FFE56C?alt=media&token=8198df4e-da8c-4883-b278-fc7c14730f69, "title": blacks don’t Crack , "price": 23, "type": Abstract, "userUID": 4bjurh5FFNOUb2D4oHGfRqEm7Il2]
DIC: ["artWidth": 11, "height": 81, "private": 0, "artHeight": 81, "description": Yes , "postDate": 1502242913081, "width": 118, "imageUrl": https://firebasestorage.googleapis.com/v0/b/medici-b6f69.appspot.com/o/Art%2F4bjurh5FFNOUb2D4oHGfRqEm7Il2%2F305FDE5C-1C5C-4ABD-B4A1-4FA224421202?alt=media&token=fcba57df-e252-47c2-be92-7836bd97e6fe, "title": Title , "price": 23, "type": type, "userUID": 4bjurh5FFNOUb2D4oHGfRqEm7Il2]
DIC: ["height": 82, "private": 0, "width": 124, "postDate": 1503341277594, "description": Hey , "title": Title , "imageUrl": https://firebasestorage.googleapis.com/v0/b/medici-b6f69.appspot.com/o/Art%2F4bjurh5FFNOUb2D4oHGfRqEm7Il2%2F04B00727-2AE4-41E3-BCA3-3980182C7F67?alt=media&token=cc1d6a92-1625-453c-bf1f-2ec84d6df51a, "userUID": 4bjurh5FFNOUb2D4oHGfRqEm7Il2, "price": 23, "type": Modern]

Could you please attach the output of print(dictionary) and print(snapshot.value) before calling ArtViewModelController.parse(dictionary)?
var arts = [Art?]()
print(dictionary) // -> output #1
print(snapshot.value) // -> output #2
if let art = ArtViewModelController.parse(dictionary) {
arts.append(art)
[...]

You could try the following two options.
Option #1
This should work with the assumption that snapshot.value returns the full dictionary (array of 12 items):
func retrieveVideos(_ completionBlock: #escaping (_ success: Bool, _ error: Error?) -> ()) {
let userMessagesRef = DataService.instance.REF_ARTISTARTS.child(Auth.auth().currentUser!.uid)
userMessagesRef.observe(.childAdded, with: { [weak self] (snapshot) in
guard let dictionary = snapshot.value as? [String: AnyObject] else {
completionBlock(false, nil)
return
}
guard let strongSelf = self else {return}
var arts = [Art?]()
if let art = ArtViewModelController.parse(dictionary) {
arts.append(art)
}
strongSelf.viewModels = ArtViewModelController.initViewModels(arts)
completionBlock(true, nil)
}) { (error: Error) in
completionBlock(false, error)
}
}
Option #2
If it works, Option #1 is the simpler solution. Otherwise, as it looks like the content of each DataSnapshot is a dictionary, the following code may work:
func retrieveVideos(_ completionBlock: #escaping (_ success: Bool, _ error: Error?) -> ()) {
let userMessagesRef = DataService.instance.REF_ARTISTARTS.child(Auth.auth().currentUser!.uid)
userMessagesRef.observe(.childAdded, with: { [weak self] (snapshot) in
guard let strongSelf = self else {return}
var arts = [Art?]()
for snapshotItem in snapshot.children.allObjects as? Dictionary {
let art = Art(snapshot: snapshotItem)
arts.append(art)
}
strongSelf.viewModels = ArtViewModelController.initViewModels(arts)
completionBlock(true, nil)
}
}) { (error: Error) in
completionBlock(false, error)
}
You should add Art(snapshot: Dictionary) to the Art class:
// Initialize Art from dictionary
func Art(snapshot: Dictionary) {
let artID = dictionary["userUID"] as? String ?? ""
let imgUrl = dictionary["imageUrl"] as? String ?? ""
let title = dictionary["title"] as? String ?? ""
let description = dictionary["description"] as? String ?? ""
let price = dictionary["price"] as? NSNumber ?? 0
let type = dictionary["type"] as? String ?? ""
let height = dictionary["artHeight"] as? NSNumber ?? 0
let width = dictionary["artWidth"] as? NSNumber ?? 0
let postDate = dictionary["postDate"] as? NSNumber ?? 0
return Art(artID: artID, imgUrl: imgUrl, price: price, title: title, description: description, type: type, height: height, width: width, postDate: postDate)
}
NOTE: I assumed the key you are looking for in the DataSnapshot is userUID as I didn't see an artID (as is in the parsing code).

Use This: -
func retrieveVideos(_ completionBlock: #escaping (_ success: Bool, _ error: Error?) -> ()) {
let userMessagesRef = DataService.instance.REF_ARTISTARTS.child(Auth.auth().currentUser!.uid)
userMessagesRef.observe(.value, with: { [weak self] (snapshot) in
if let snapshots = snapshot.children.allObjects as? [DataSnapshot]
{
print("SNAPSHOT: (snapshots.count)")
}
var arts = [Art]()
guard let strongSelf = self else {return}
for snapshot in snapshots {
let dictionary = snapshot.value as? [String: AnyObject]
if let art = ArtViewModelController.parse(dictionary) {
arts.append(art)
}
}
strongSelf.viewModels = ArtViewModelController.initViewModels(arts)
completionBlock(true, nil)
}) { (error: Error) in
completionBlock(false, error)
}
}

Related

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 merge two datasourcemodel using mvvm in swift

I have two datasource model.I am doing in mvvm.
My datasourcemodel is as below.
class QuestionDataSourceModel: NSObject {
var dataListArray:Array<QuestionListModel>? = []
var list:Array<OptionsModel>? = []
init(array :Array<[String:Any]>?) {
super.init()
var newArray:Array<[String:Any]> = []
if array == nil{
// newArray = self.getJsonDataStored22()
}
else{
newArray = array!
}
var datalist:Array<QuestionListModel> = []
for dict in newArray{
let model = QuestionListModel(dictionary: dict)
datalist.append(model)
}
self.dataListArray = datalist
print(self.dataListArray)
}
}
the above is first datasourcemodel.
Next datasourcemodel is as below.
class DummyDataSourceModel: NSObject {
var dataListArray:Array<DummyDataModel>? = []
var list:Array<DummyDataModel>? = []
init(array :Array<[String:Any]>?) {
super.init()
var newArray:Array<[String:Any]> = []
if array == nil{
// newArray = self.getJsonDataStored22()
}
else{
newArray = array!
}
var datalist:Array<DummyDataModel> = []
for dict in newArray{
let model = DummyDataModel(dictionary: dict)
datalist.append(model)
}
self.dataListArray = datalist
print(self.dataListArray)
}
}
In my view controller :-
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("")
}
//questionViewModel.numberOfSections()
self.activityindicator.stopAnimating()
self.activityindicator.isHidden = true
self.tableview.refreshControl = refreshControl
self.tableview .allowsMultipleSelection = false
self.tableview.reloadData()
// self.questionViewModel.loadData2{ (isSuccess) in
self.dummyDataViewModel.loadData1{ (isSuccess) in
if(isSuccess == true)
{
print(self.questionViewModel.datasourceModel.dataListArray?.count)
self.questionViewModel.totaldata()
self.tableview2.allowsMultipleSelection = false
self.tableview2.reloadData()
}
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)
}
}
MY QuestionViewModel:-
func loadFromWebserviceData(completion :#escaping (QuestionDataSourceModel?) -> ()){
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)
if let data = wholedata["data"] as? Array<[String:Any]>{
print(data)
print(response)
for question in data {
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:QuestionDataSourceModel = QuestionDataSourceModel(array: data)
completion(newDataSource)
}
}
case .failure(let encodingError ):
print(encodingError)
// if response.response?.statusCode == 404{
print(encodingError.localizedDescription)
completion(nil)
}
}}
func loadData(completion :#escaping (_ isSucess:Bool) -> ()){
loadFromWebserviceData { (newDataSourceModel) in
if(newDataSourceModel != nil)
{
self.datasourceModel = newDataSourceModel!
completion(true)
}
else{
completion(false)
}
}
}
my dummyViewModel is below:-
func loadFromDummyData(completion :#escaping (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
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:DummyDataSourceModel = 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)
}
}
}
Now i need to merge this two datasourceModel.
I am using tableview to display the data .
So first i need to display the data from the JSON.then below i need to display the data from the json.file.So how to merge this two datasourcemodel.
First the data from JSON has 10 sections.
In json.file it has 3 sections.So total 13 sections .So i need to display the 13 sections together in the tableview.How to do?
This the json.file data:-
{
"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"]
}
]
}
And same format forJSON from api.
{
"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"]
}
]
}
class OptionsModel: NSObject {
var options: [String]?
var question: String?
var button_type: String?
}
class OptionsViewModel: NSObject {
var optionList: Array<OptionsModel>?
func callApi() {
yourApiCall() { webResponseArray in
for res in webResponseArray {
let model = OptionsModel(json: res)
if optionList == nil {
optionList = [OptionsModel]()//Initialize Array if not initialized
}
optionList.append(model)// You are appending Option getting from web Api Response
}
//After Completely fetching all models from webResponseArray you should load Data from Local JSON
loadLocalJSON()//After loading Data from Web You are loading Data from local JSON.
}
}
func loadLocalJSON() {
let localJsonArray = someMethodToLoadJsonFromLocalFileAndReturnsJSON()
for json in localJsonArray {
let model = OptionsModel(json: json)
if optionList == nil {
optionList = [OptionsModel]()//Initialize Array if not initialized
}
optionList.append(model)// You are appending Option getting from Local JSON
}
//Now you have a single Array containing all local and remote option models.
}
}

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.

How to loop array imageURL in JSON for show in image view

I have function for loop data(title, price, drug) JSON But I can't loop imageUrl to show in imageview on this function please help see my code.
This function barcodeReaded
func barcodeReaded(barcode: String) {
print("Barcode is: \(barcode)")
showCodeLabel.text = barcode
let data = NSData(contentsOfURL: episode.thumbnailURL!)
let image = UIImage(data: data!)
self.thumbnailImageView.image = image
let episodes = Episode.downloadAllEpisodes()
var filteredEpisodes = episodes.filter({ $0.testCode == barcode })
if filteredEpisodes.count > 0 {
titleLabel.text = filteredEpisodes[0].title
drugLabel.text = filteredEpisodes[0].drug
priceLabel.text = filteredEpisodes[0].price
//thumbnailImageView.image = filteredEpisodes[0].thumnailURL
}
}
This JSON file
{
"episode": [
{
"testCode": "11111111",
"title": "Stomachic mixture 180 ml",
"drug": "AAAAA",
"thumbnailURL": "https://firebasestorage.googleapis.com/v0/b/rxscan-a14ee.appspot.com/o/j01.jpg?alt=media&token=5718797b-fc9c-416e-9394-b544c2880dc9",
"price": "100"
},
{
"testCode": "22222222",
"title": "Parasetamol 200 ml",
"drug": "BBBBB",
"thumbnailURL": "urlImage",
"price": "150"
},
{
"testCode": "33333333",
"title": "Beramol 300 ml",
"drug": "CCCCC",
"thumbnailURL": "urlImage",
"price": "120"
}
]
}
This some code
import Foundation
class Episode
{
var title: String?
var thumbnailURL: NSURL?
var drug: String?
var price: String?
var testCode: String?
init(title: String, thumbnailURL: NSURL, drug: String, price: String, testCode: String)
{
self.title = title
self.thumbnailURL = thumbnailURL
self.drug = drug
self.price = price
self.testCode = testCode
}
typealias EpisodeDictionary = [String : AnyObject]
init(espDictionary: EpisodeDictionary)
{
self.title = espDictionary["title"] as? String
self.thumbnailURL = NSURL(string: espDictionary["thumbnailURL"] as! String)
self.drug = espDictionary["drug"] as? String
self.price = espDictionary["price"] as? String
self.testCode = espDictionary["testCode"] as? String
}
static func downloadAllEpisodes() -> [Episode]
{
var episodes = [Episode]()
let jsonFile = NSBundle.mainBundle().pathForResource("testJson3edit6", ofType: "json")
let jsonData = NSData(contentsOfFile: jsonFile!)
if let jsonDictionary = NetworkService.parseJSONFromData(jsonData) {
let espDictionaries = jsonDictionary["episodes"] as! [EpisodeDictionary]
for dict in espDictionaries {
let episode = Episode(espDictionary: dict)
episodes.append(episode)
}
}
return episodes
}
}
NetworkService.swift
import Foundation
class NetworkService
{
// TODO: Make this class be able to download images from a URL
lazy var configuration: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
lazy var session: NSURLSession = NSURLSession(configuration: self.configuration)
let url: NSURL
init(url: NSURL)
{
self.url = url
}
func downloadImage(completion: (NSData -> Void))
{
let request = NSURLRequest(URL: self.url)
let dataTask = session.dataTaskWithRequest(request) { (data, response, error) in
if error == nil {
if let httpResponse = response as? NSHTTPURLResponse {
switch (httpResponse.statusCode) {
case 200:
if let data = data {
completion(data)
}
default:
print(httpResponse.statusCode)
}
}
} else {
print("Error download data: \(error?.localizedDescription)")
}
}
dataTask.resume()
}
}
extension NetworkService
{
static func parseJSONFromData(jsonData: NSData?) -> [String : AnyObject]?
{
if let data = jsonData {
do {
let jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? [String : AnyObject]
return jsonDictionary
} catch let error as NSError {
print("Error processing json data: \(error.localizedDescription)")
}
}
return nil
}
}
This code for get image that use in detailViewController Which I don't know how to apply with function barcodeReaded.
if episode.thumbnailURL != nil {
if let thumbnailURL = episode.thumbnailURL {
let networkService = NetworkService(url: thumbnailURL)
networkService.downloadImage({ (data) in
//thumbnailImageView.image = episode.thumbnailURL
let image = UIImage(data: data)
dispatch_async(dispatch_get_main_queue(), {
self.thumbnailImageView.image = image
})
})
}
}
Basically with thumbnailImageView.image = episode.thumbnailURL your are trying to assign a String to an object of type UIImage.
You should do it:
1. Get NSURL from your json string
let url = NSURL(string: episode.thumbnailURL)!
2. Get the NSData of that NSURL
let data = NSData(contentsOfURL: url)!
3. Assign the UIImage from NSData
let image = UIImage(data: data)
self.thumbnailImageView.image = image

Resources