Looping an array received from service - ios

JSON from service
{
"firstname": "Utku",
"lastname": "Dalmaz",
"photos": [{
"src": "image",
"post_id": "69"
}, {
"src": "image",
"post_id": "74"
}, {
"src": "image",
"post_id": "133"
}, {
"src": "image",
"post_id": "142"
}]}
SWIFT CODE
Alamofire.request("SERVICE", method: .post, parameters: parameters).validate().responseJSON { response in
switch response.result {
case .success:
if let json = response.result.value {
var success = 0
if let dictJSON = json as? [String: AnyObject] {
if let successInteger = dictJSON["success"] as? Int {
success = successInteger
if success == 1
{
self.firstname = dictJSON["firstname"] as! String
self.lastname = dictJSON["lastname"] as! String
if let photos = dictJSON["photos"] as! Array<String> {
let postID = //post_id data
let src = //src data
let data = InboxPhotos(ID: postID!, src: src!)
self.photosArr.append(data)
}
...
I am trying to get array data from JSON service. Even though I am able to get firstname and lastname data, I cannot get and loop photos array in swift code.
How can I loop photos array and get post_id and src data into InboxPhotos and append to photosArr array?

let dictJSON = ...
guard let photos = dictJSON?["photos"] as? [[String: Any]] else { return }
let list = photos.map { InboxPhotos(ID: $0["post_id"] as! String, src: $0["src"] as! String)}
// Or more safely.
let list2: [InboxPhotos] = photos.compactMap {
guard let src = $0["src"] as? String,
let id = $0["post_id"] as? String else {
return nil
}
return InboxPhotos(ID: id, src: src)
}

I have made JSON parsing modal for your JSON Data-Type. you don't need anything just pass data at the time create a modal object and get data without hectic.
struct UserModal{
var firstname:String
var lastname:String
var photos: [PhotosModal]
init(dictData:[String: Any]) {
self.firstname = dictData["firstname"] as? String ?? ""
self.lastname = dictData["lastname"] as? String ?? ""
var photosArr = [PhotosModal]()
for data in dictData["photos"] as? [[String:Any]] ?? [] {
photosArr.append(PhotosModal(src: data["src"] as! String, post_id: data["post_id"] as! Int))
}
self.photos = photosArr
}
}
struct PhotosModal{
var src:String
var post_id:Int
init(src:String, post_id:Int) {
self.src = src
self.post_id = post_id
}
}
let userModal = UserModal(dict: dictJSON?["photos"] as? [[String: Any]])
So Make separate file for this modal file. Applying this you will follow Single responsibility class/file of SOLID principal rules.

Related

ios swift - functions causes indexing to take forever and not build [duplicate]

This question already has answers here:
Xcode 8.1 swift 3 take forever to compile this code
(3 answers)
Closed 5 years ago.
Hopefully someone has an answer for this.
I spent hours figuring out why xcode took forever compiling and why it was stuck at building/indexing. I found out it was because of these two functions:
public func setLocationsToSession(view: UIViewController, Completion callback: #escaping (_ status: String) -> Void) {
getStudentLocations(view: view){(error, data) in
print("setting session")
print(data)
if let results = data!["results"] {
for student in results as! [AnyObject] {
// check the object for the required keys/subscripts
if let objectId = student["objectId"], let uniqueKey = student["uniqueKey"], let fname = student["firstName"], let lname = student["lastName"], let mapString = student["mapString"], let mediaURL = student["mediaURL"], let lat = student["latitude"], let lng = student["longitude"], let createdAt = student["createdAt"], let updatedAt = student["updatedAt"] {
// some other students are forgetting to POST/PUT the required key-value pairs in their request(s),
// and it breaks my code/app. So this is why i have all of these optional defaults
if(fname as String == "" || lname as String == "" || lat as String == "" || lng as String == "" || lat == 0 || lng == 0) {
// ignore the bad ones
continue
}
let newStudent = Student(dict: [
"objectId": objectId as? String ?? "",
"uniqueKey": uniqueKey as? String ?? "",
"firstName": fname as! String,
"lastName": lname as! String,
"mapString": mapString as? String ?? "",
"mediaURL": mediaURL as? String ?? "",
"latitude": lat as! Double ?? 0.0,
"longitude": lng as? Double ?? 0.0,
"createdAt": createdAt as? String ?? "",
"updatedAt": updatedAt as? String ?? ""
])
session.studentLocations.append(newStudent)
}
else {
continue
}
}
}
else {
let value = keys.error
callback(value)
}
let value = error == true ? keys.error : keys.success
callback(value)
}
}
public func getStudentLocation(view: UIViewController, key: String, Completion callback: #escaping (_ Error: Bool) -> Void) {
var reqDICT: [String: Any] = [String:Any]()
reqDICT["url"] = "https://parse.udacity.com/parse/classes/StudentLocation?where={\"uniqueKey\":\"\(key)\"}"
reqDICT["method"] = "GET"
let request = NSMutableURLRequest(url: URL(string: escapeString(value: reqDICT["url"] as! String))!)
request.httpMethod = reqDICT["method"] as! String
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("QrX47CA9cyuGewLdsL7o5Eb8iug6Em8ye0dnAbIr", forHTTPHeaderField: "X-Parse-Application-Id")
request.addValue("QuWThTdiRmTux3YaDseUSEpUKo7aBYM737yKd4gY", forHTTPHeaderField: "X-Parse-REST-API-Key")
reqDICT["request"] = request
httpRequest(view: view, requestDICT: reqDICT) {(error, data) in
print("error: \(error) ; data: \(data)")
if let results = data!["results"], results.count > 0 {
print("results exist: \(results.count)")
let Res = results as! [[String:AnyObject]]
let student = Res[0] as! AnyObject
print("results: \(results)")
print("student: \(student)")
let newStudent = Student(dict: [
"objectId": student["objectId"] as? String ?? "",
"uniqueKey": student["uniqueKey"] as? String ?? "",
"firstName": student["firstName"] as? String ?? "",
"lastName": student["lastName"] as? String ?? "",
"mapString": student["mapString"] as? String ?? "",
"mediaURL": student["mediaURL"] as? String ?? "",
"latitude": student["latitude"] as? Double ?? 0.0,
"longitude": student["longitude"] as? Double ?? 0.0,
"createdAt": student["createdAt"] as? String ?? "",
"updatedAt": student["updatedAt"] as? String ?? ""
])
session.you = newStudent
session.objID = student["objectId"] as! String
session.dataExists = true
}
else {
session.dataExists = false
}
callback(error)
}
}
I created these functions to handle the JSON response from an HTTP Request. The problem is that not all of the json objects in the results array have the same keys; some don't have keys that others do. That's why in these two functions I wrote, I tried to unwrap the keys in the JSON object in the if let statement and when I'm instantiating a new struct to prevent nil. That is what is causing xcode to take forever compiling because when I commented those two out, it compiled/build/run in seconds. How else can I go about this? Thanks!
It's the dictionary literals. If you want to speed things up, create the dictionary the normal way, then add all the items, eg:
var newStudent = [String: String]()
newStudent["objectId"] = student["objectId"] as? String ?? ""
// etc...

how to get the JSONArray from jsonObject in Swift 3.1

{
"status": true,
"status_code": 1,
"content": [
{
"cat_id": "3",
"cat_name": "Food",
"cat_parentid": "2"
},
{
"cat_id": "4",
"cat_name": "Entertainment",
"cat_parentid": "2"
},
{
"cat_id": "5",
"cat_name": "Cars",
"cat_parentid": "2"
},
{
"cat_id": "12",
"cat_name": "Personal Care",
"cat_parentid": "2"
}
],
"message": "Success"
}
UPDATE
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
completion((json as? AnyObject)!) //here completion callback will return the jsonObject to my UIViewController.
}
} catch let error {
print(error.localizedDescription)
}
this is my JSONObject. I am very new to the swift. how to get the content JSONArray and further process in swift.? Anybody can help me? Help will be appreciated.
This code checks if the status is true, gets the array for key content and prints all values in the array.
The array is clearly [[String:String]] so cast the object to this specific type.
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
if let status = json["status"] as? Bool, status == true {
if let content = json["content"] as? [[String:String]] {
for category in content {
let id = category["cat_id"]
let name = category["cat_name"]
let parentId = category["cat_parentid"]
print(id , name, parentId)
}
}
}
}
} catch let error {
print(error.localizedDescription)
}
PS: As always, never use .mutableContainers in Swift. It's meaningless
Check whether your json has content array
if let content = json["content"] as? [Dictionary<String, AnyObject>] {
print(content) // it will give you content array
}
Get content array like this:
let allContent = json["content"] as? [[String: Any]]
Full sample:
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
if let allContent = json["content"] as? [[String: Any]] {
for content in allContent {
let catId = content["cat_id"] as? String
let catName = content["cat_name"] as? String
let catParentId = content["cat_parentid"] as? String
print(">> catid=" + catId!)
print(">> catName=" + catName!)
print(">> catparentID=" + catParentId!)
}
}
}
} catch let error {
print(error.localizedDescription)
}
let content = dict.objectForKey("content")! as NSArray
Then you can get json of single object for parsing by
for var cat in content
{
print(cat)
}
Another alternative way, by using the library.
First, import JSON library for Swift - SwiftyJSON and use the code:
import SwiftyJSON
let json = JSON(<jsonObject data>)
let contentArray: Array<JSON> = json["content"].arrayValue
Library Integration
If you're using cocoapods then use this pod:
pod 'SwiftyJSON'
OR else just drag SwiftyJSON.swift to the project tree.
you can extract you data by providing key
if let array = result["content"] as? Array<AnyObject> {
print(arry)
}
You can access like below
if let filePath = Bundle.main.path(forResource: "sample", ofType: "json"), let data = FileManager().contents(atPath: filePath) {
do {
let dicRes = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any]
let contentArray = dicRes?["content"]
print("contentArray == \(contentArray)")
} catch {
}
}

JSON structure with Swift and Alamofire

Following on from This question
I am trying to bring in the summary field but it has a further value. I have brought in the title and author as follows:
func parseData(JSONData : Data) {
do {
var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONstandard
// print(readableJSON)
if let posts = readableJSON["posts"] as? [JSONstandard] {
for post in posts {
let title = post["title"] as! String
let author = post["author"] as! String
let summary = post["summary"] as! String
print(author)
if let imageUrl = post["image"] as? String {
let mainImageURL = URL(string: imageUrl )
let mainImageData = NSData(contentsOf: mainImageURL!)
let mainImage = UIImage(data: mainImageData as! Data)
postsinput.append(postinput.init(mainImage: mainImage, name: title, author: author, summary: summary))
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
catch {
print(error)
}
}
But if i try the summary that way a error is returned. Any help would be appreciated.
JSON STRUCTURE
{
"posts" : [{
"id": "000000",
"url": "/content/interview2",
"date": "2016-11-03 09:01:41",
"modified": "2016-11-03 09:03:47",
"title": "An interview",
"image": "https://www.example.com/sites/default/files/oregood.jpeg",
"summary": {
"value": "<p>Latin text here</p>",
"format": "filtered_html"
}
}]
}
From your previous question response, summary key contains the Dictionary so you can try like this.
guard let dic = post["summary"] as? [String: Any], let summary = dic["value"] as? String else {
return
}

Values are not updating in my text label from api calling

I have one api calling, and I am passing one parameter value to that api. And I am doing append to one model data and from there I am trying to display in my label. But when I do api calling itself and try to print the label name , Its showing crash index out of range
func showprofileapi () {
let headers = [
"cache-control": "no-cache",
"postman-token": "4c933910-0da0-b199-257b-28fb0b5a89ec"
]
let jsonObj:Dictionary<String, Any> = [
"customerID" : "5"
]
if (!JSONSerialization.isValidJSONObject(jsonObj)) {
print("is not a valid json object")
return
}
if let postData = try? JSONSerialization.data(withJSONObject: jsonObj, options: JSONSerialization.WritingOptions.prettyPrinted) {
let request = NSMutableURLRequest(url: NSURL(string: "http://MyProfile.php")! as URL,
cachePolicy: .useProtocolCachePolicy,timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
///print(error)
} else {
DispatchQueue.main.async(execute: {
if let json = (try? JSONSerialization.jsonObject(with: data!, options: [])) as? Dictionary<String,AnyObject>
{
let status = json["status"] as? Int;
if(status == 1)
{
print("SUCCESS....")
if (json["myprofile"] as? NSDictionary) != nil
{
print("SUCCESS ......22....")
print(json)
DispatchQueue.main.async(execute: {
print("INSIDE CATEGORIES")
self.Profileddatas.append(MyProfiledData(json:json as NSDictionary))
print("Product Name : ", self.Profileddatas[0].custName)
})
}
}
}
})
}
})
dataTask.resume()
}
}
My above code is my api calling, And when I try to print the value in my console its crashing :
// print("Product Name : ", self.Profileddatas[0].custName)
My json output after api calling is :
{
"status": 1,
"message": "My Profile Details are.",
"myprofile": {
"CustomerName": "ram",
"CustomerEmail": "ram#gmail.com",
"CustomerMobile": "",
"CustomerAddress": "",
"CustomerUsername": "",
"CustomerPassword": " "
}
}
My append data model class is :
class MyProfiledData
{
var custName : String?
var custEmail : String?
var custMobile : String?
var custAddress : String?
var custUsername : String?
var custPassword : String?
init(json:NSDictionary)
{
self.custName = json["CustomerName"] as? String
self.custEmail = json["CustomerEmail"] as? String
self.custMobile = json["CustomerMobile"] as? String
self.custAddress = json["CustomerAddress"] as? String
self.custUsername = json["CustomerUsername"] as? String
self.custPassword = json["CustomerPassword"] as? String
}
}
Please help me out.
Thanks
change if (json["myprofile"] as? NSDictionary) != nil
to if let json = json["myprofile"] as? NSDictionary because your 'json' in the context of initializing MyProfiledData went wrong
You're accessing the JSON Data by it's wrong keys in Your MyProfileData Class. You have either pass the ["myprofile"] dict in the init(json) call by
if let myProfile = json["myprofile"] as? NSDictionary {
DispatchQueue.main.async(execute: {
self.Profiledatas.append(MyProfileData(json:myProfile))
})
}
or access it by their right Keys:
class MyProfiledData {
var custName : String?
var custEmail : String?
var custMobile : String?
var custAddress : String?
var custUsername : String?
var custPassword : String?
init(json:NSDictionary) {
self.custName = json["myprofile"]["CustomerName"] as? String
self.custEmail = json["myprofile"]["CustomerEmail"] as? String
self.custMobile = json["myprofile"]["CustomerMobile"] as? String
self.custAddress = json["myprofile"]["CustomerAddress"] as? String
self.custUsername = json["myprofile"]["CustomerUsername"] as? String
self.custPassword = json["myprofile"]["CustomerPassword"] as? String
}
}
In your init function it structure is not ok, it will be work if you send only my profile node of your json
{
"CustomerName": "ram",
"CustomerEmail": "ram#gmail.com",
"CustomerMobile": "",
"CustomerAddress": "",
"CustomerUsername": "",
"CustomerPassword": " "
}
use
self.Profileddatas.append(MyProfiledData(json:Json["myprofile"] as NSDictionary))
if (json["myprofile"] as? NSDictionary) != nil
{
print("SUCCESS ......22....")
print(json)
DispatchQueue.main.async(execute: {
print("INSIDE CATEGORIES")
self.Profileddatas.append(MyProfiledData(json:json["myprofile"] as! NSDictionary))
print("Product Name : ", self.Profileddatas[0].custName)
self.getvalue ()
})
}

JSON Structure for parsing JSON data

I want to parse this JSON,at the top level incoming JSON is an array,how can access to information of dictionary in array?
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere#april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
}
]
that is my code but I don't know how detect dictionary data.
func profileFromJSONData(data : NSData) -> ProfileResult {
do{
let jsonObject : [[String:AnyObject]]
= try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [[String:AnyObject]]
for profileJSON in jsonObject {
if let profile = profileFromJsonObject(profileJSON) {
finalProfile.append(profile)
}
}
return .Success(finalProfile)
}
catch let error {
return .Failure(error)
}
}
it is my profileFromJsonObject method for parse JSON into profile instance
func profileFromJsonObject(json: [String:AnyObject]) -> UserProfile?{
guard let
id = json["id"] as? Int,
name = json["name"] as? String,
userName = json["username"] as? String,
email = json["email"] as? String,
address = json["address"] as? NSDictionary,
phone = json["phone"] as? String,
website = json["website"] as? String,
company = json["company"] as? NSDictionary
else {
return nil
}
let obj = UserProfile(id: id, name: name, userName: userName, email: email, address: address, phone: phone, website: website, company: company)
return obj
}
I tried your JSON by taking it in local file, and I am able to parse to the model object in following way.
You just put your remote JSON in my code, i hope it will work
func getTheLocalJSON()
{
let filePath = NSBundle.mainBundle().pathForResource("test", ofType: "json");
let data = NSData.init(contentsOfFile: filePath!);
var json : NSArray!
do{
json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! NSArray;
}catch{
}
print("json \(json)");
let dictResponse = json.objectAtIndex(0) as! NSDictionary;
let objUser = profileFromJsonObject(dictResponse)! as UserProfile;
print("user : \(objUser)");
//Code to access company name and show it as screen title
self.title = (objUser.company)!["name"] as? String;
lblCompanyname.text = (objUser.company)!["name"] as? String;
lblCatchPhrase.text = (objUser.company)!["catchPhrase"] as? String;
lblbs.text = (objUser.company)!["bs"] as? String;
}
func profileFromJsonObject(json: NSDictionary) -> UserProfile?{
guard let
id = json["id"] as? Int,
name = json["name"] as? String,
userName = json["username"] as? String,
email = json["email"] as? String,
address = json["address"] as? NSDictionary,
phone = json["phone"] as? String,
website = json["website"] as? String,
company = json["company"] as? NSDictionary
else {
return nil
}
let obj = UserProfile(id: id, name: name, userName: userName, email: email, address: address, phone: phone, website: website, company: company)
return obj
}
Output :

Resources