Can't execute NSURLSession.sharedSession().dataTaskWithURL in Swift - ios

I have a code to get an employee data from php returned Json which is the following :
[{"id":"1","email":"KK","password":"KKK","firstName":"KKK","lastName":"KK","photo":null,"phone":"22","mobile":"2","position":"SS","adminstrator_id":"1","department_id":"1"}]
Code I have try:
func getEmpById (id:String) {
emp = employee()
let myUrl = NSURL(string:"http://localhost/On%20Call%20App/scripts/getEmployee.php?id=\(id)")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(myUrl!, completionHandler: {
(data, response, error) -> Void in
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! [[String: AnyObject]]
let dic = json[0]
if let id = dic["id"] , firstName = dic["firstName"] ,lastName = dic["lastName"], mobile = dic["mobile"],phone = dic["phone"],email=dic["email"],pos=dic["position"]{
self.emp.setId(id as! String )
self.emp.setFirstName(firstName as! String)
self.emp.setLastName(lastName as! String)
self.emp.setPhone(phone as! String)
self.emp.setMobile(mobile as! String)
self.emp.setEmail(email as! String)
self.emp.setPosition(pos as! String)
}
} catch {
print(error)
}
})
task.resume()
}
The problem in this line let task = session.dataTaskWithURL(myUrl!, completionHandler:{ when the app reach this line it will directly go to task.resume() without printing any error
Any help to make this work ?

Your response is of Array type not Dictionary
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! NSArray
let dic = json[0] as! NSDictionary
print(dic.objectForKey("email"))
It is batter if use use Swift array like this.
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! [[String: AnyObject]]
let dic = json[0]
print(dic["email"])

Related

Working with JSON data retrieving into Swift data types

I'm trying to get data from a URL. It was successful. I can download and convert to a dictionary[String : Any] but response is in nested loops. I don't to how to retrieve. Can someone suggest how to get text and value in the response?
func getDataFromUrl() {
let url = URL(string: "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&departure_time=1408046331&origins=37.407585,-122.145287&destinations=37.482890,-122.150235")
let request = NSMutableURLRequest(url: url!)
let session = URLSession.shared
request.httpMethod = "GET"
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
do {
let jsonData = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any]
let destinationAddress = jsonData!["destination_addresses"]
print("Destination address \(String(describing: destinationAddress!))")
let origin_addresses = jsonData!["origin_addresses"]
print("Origin_addresses \(String(describing: origin_addresses!))")
let rows = jsonData!["rows"]
print("Rows \(String(describing: rows!))")
// Here I want to print text and value.
} catch {
// handle error
}
})
dataTask.resume()
}
The above answers work, but in my opinion the more swiftier approach is to use Codable.
class MyResponseType:Codable {
let destination_addresses:String
let rows:[MyCustomRowData]
}
class MyCustomRowData:Codable {
let elements:[MyCustomElementsData]
}
class MyCustomElementsData:Codable {
// properties here
}
Doing this, parsing the json is done like this:
let response = try? JSONDecoder().decode(MyResponseType.self, from: data)
Where the data variable is just the retrieved Data object from the request.
Initially you have to set up some boilerplate code to replicate your expected data format, but working with it is really worth it (and it makes it highly testable).
When the decode succeeds you have a perfectly typed object, it can also have optionals. It just wont decode if fields are missing or of the wrong type (which is a good thing).
Here is the way you can parse text and Value from response:
do{
if let jsonData = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any] {
if let destinationAddress = jsonData["destination_addresses"] as? [String] {
print(destinationAddress) //["1 Hacker Way, Menlo Park, CA 94025, USA"]
}
if let origin_addresses = jsonData["origin_addresses"] as? [String] {
print(origin_addresses) //["3251 Hillview Ave, Palo Alto, CA 94304, USA"]
}
if let rows = jsonData["rows"] as? [[String: AnyObject]] {
if rows.indices.contains(0) {
if let elements = rows[0]["elements"] as? [[String: AnyObject]] {
for element in elements {
if let duration = element["duration"] as? [String: AnyObject] {
let text = duration["text"] as? String ?? ""
print(text) //17 mins
let value = duration["value"] as? Int ?? 0
print(value) //1010
}
if let distance = element["distance"] as? [String: AnyObject] {
let text = distance["text"] as? String ?? ""
print(text) //7.2 mi
let value = distance["value"] as? Int ?? 0
print(value) //11555
}
}
}
}
}
}
}catch{ //error handle
}
Use this code:
let rows = jsonData["rows"] as! Array
let element = rows[0] as! Dictionary
let elementArray = element.value(forKey: "elements")
let distance = elementArray[0].value(forKey: "distance")
let text = distance.value(forKey: "text")
print(text)
let value = distance.value(forKey: "value")
print(value)

how to parse the children array using json in swift 3?

In this i need to get the elements from children array which will be in below mentioned url and i need to get the children array from all 11 objects can anyone help me how to implement this ?
let url = "http://www.json-generator.com/api/json/get/cwqUAMjKGa?indent=2"
var detailsArray :[[String: AnyObject]] = []
var productName = [String]()
var childrenArray :[[String: AnyObject]] = []
override func viewDidLoad() {
super.viewDidLoad()
downloadJsonWithURL()
// Do any additional setup after loading the view.
}
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]])!
print(self.detailsArray)
for item in self.detailsArray{
if let detailDict = item as? NSDictionary {
if let name = detailDict.value(forKey: "name"){
self.productName.append(name as! String)
}
}
}
OperationQueue.main.addOperation({
print(self.productName)
print(self.childrenArray)
})
}
}).resume()
}
iterate the detailsArray and for key "children" append the data to childrenArray
for item in self.detailsArray {
if let detailDict = item as? [String: Any] {
if let child = detailDict["children"] {
self. childrenArray.append(child)
}
}
}
Try out this :
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]])!
print(self.detailsArray)
for item in self.detailsArray{
if let detailDict = item as? [String:Any] {
if let name = detailDict["name"] as? String {
self.productName.append(name as! String)
}
if let children = detailDict["children
"] as? [Any] {
self.childrenArray.append(children)
}
}
}
OperationQueue.main.addOperation({
print(self.productName)
print(self.childrenArray)
})
}
}).resume()
}

" Type any has no subscript member in swift3.0 " how to resolve it?

do{
//converting response to NsDictionary
var myJSON:NSDictionary!
myJSON=try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:Any] as NSDictionary!
//getting the json response
let questions:NSArray = myJSON["questions"] as! NSArray
//looping through all the array
for i in 0 ..< questions.count{
//getting the json for each index
//let i=0
self.questionId = questions[i]["id"] as! Int
let questionName:String = questions[i]["ques"] as! String?
let questionopta:String = questions[i]["opta"] as! String!
let questionoptb:String = questions[i]["optb"] as! String!
let questionoptc:String = questions[i]["optc"] as! String!
let questionoptd:String = questions[i]["optd"] as! String!
try this ..
do{
var myJSON:[String:Any]!
myJSON = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:Any]
//getting the json response
let questions = myJSON["questions"] as! [[String:Any]]
//looping through all the array
for obj in questions{
self.questionId = obj["id"] as! Int
let questionName = obj["ques"] as! String
let questionopta = obj["opta"] as! String
let questionoptb = obj["optb"] as! String
let questionoptc = obj["optc"] as! String
let questionoptd = obj["optd"] as! String
And please don't make force unwrap .. this code is just for your guidance.
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String : Any] {
for question in json["questions"] as? [[String : Any]] ?? [] {
guard
let questionId = question["quid"] as? Int,
let questionName = question["ques"] as? String,
let questionopta = question["opta"] as? String,
let questionoptb = question["optb"] as? String,
let questionoptc = question["optc"] as? String,
let questionoptd = question["optd"] as? String else { continue }
self.questionId = questionId
// ...
}
}
} catch {
print(error)
}

Swift 3 Compiler Errors with JSON and Dictionaries within URLSession.shared.dataTask

After previous issues with this particular app code as 'solved' with help, a new issue has arisen with this code:
var properties: [String] = []
var unsortedDetails: [String] = []
var contacts: [[String]] = []
var propertySorting: [(key: String, ind: String, link: Bool)] = []
var autolinks: [Bool] = []
and, in the viewDidLoad function:
let contactsRequest = URLRequest(url: URL(string: "https://script.google.com/macros/s/AKfycbxOLElujQcy1-ZUer1KgEvK16gkTLUqYftApjNCM_IRTL3HSuDk/exec?id=" + ID + "&sheet=" + Industry.replacingOccurrences(of: " ", with: "+", options: NSString.CompareOptions.literal, range: nil))!)
let contactsTask = URLSession.shared.dataTask(with: contactsRequest as URLRequest)
{(data, response, error) in
do {
let jsonResult: Dictionary = try JSONSerialization.jsonObject(with: data!, options: []) as! [String : Any]
let results = jsonResult[self.Industry] as! [[String : Any]]
for key in results[0].keys {
self.propertySorting.append(key: (key as? String)!, ind: results[0].value(forKey: key as! String) as! String, link: results[1].value(forKey: key as! String) as! String != "X")
}
self.propertySorting.sort(by: {Int($0.ind) < Int($1.ind)})
for property in self.propertySorting {
self.properties.append(property.key)
self.autolinks.append(property.link)
}
for contact in results {
self.contacts.append([])
for key in self.properties {
self.contacts[self.contacts.count-1].append(contact.value(forKey: key) as! String)
}
}
DispatchQueue.main.async(execute: {
let listController = self.viewControllers[0] as! ListController
listController.properties = self.properties
listController.contacts = self.contacts
listController.autolinks = self.autolinks
listController.tableView.reloadData()
})
} catch {
print("FATAL ERROR")
}
}
contactsTask.resume()
The issues now encountered are:
Extra argument 'ind' in call when propertySorting.append(...) is called, and if this (previously working) ind section is deleted, the same error is returned for link
Instead of NSArray and NSDictionary used Swift native Array and Dictionary and use keys with Dictionary to get array of all keys.
let jsonResult: Dictionary = try JSONSerialization.jsonObject(with: data!, options: []) as! [String : Any]
let results = jsonResult[self.Industry] as! [[String : Any]]
for key in results[0].keys {
}
Note: There is no need to use .mutableContainers option with Swift native type object.

JSON Parsing & Optionals in Swift 3

So i recently updated to Swift 3/XCode 8 and some of my code went hay-wire. I've read that some syntax changes have been made but I can't seem get this one right.
I make a request to Twitter and get JSON back:
func forLoadStats(completion: (AnyObject?, NSError?) -> Void)
{
var clientError: NSError?
let idString = api.getUserID()
let client = TWTRAPIClient()
let request = client.urlRequest(withMethod: "GET", url: "https://api.twitter.com/1.1/users/show.json", parameters: ["user_id" : 27446437], error: &clientError)
client.sendTwitterRequest(request)
{ (response, data, connectionError) in
if (connectionError == nil)
{
do {
if let json: Any = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [AnyObject]
{
if let json = json, let immage = json?["profile_image_url_https"] as? String
{
//Make ProfilePic edges round
self.profPic.layer.cornerRadius = 42
self.profPic.clipsToBounds = true
//let immage = image["profile_image_url_https"] as String
let _vImageUrl = immage.replacingOccurrences(of: "_normal", with: "")
let urlProfilePic = NSURL(string: _vImageUrl)
let urlPP = NSData(contentsOf: urlProfilePic! as URL)
self.profPic.image = UIImage(data: urlPP! as Data)
let ScrName = json["screen_name"] as! String
self.scrNameLabel.text = "#\(ScrName)"
//Populate Followers Label.text
let flwrVar = json["followers_count"] as! Int
self.followerLbl.text = "\(flwrVar)"
//Populate Following Label.text
let flwngVar = json["friends_count"] as! Int
self.followingLbl.text = "\(flwngVar)"
//Populate Bio
let bio = json["description"] as! String
self.bioLabel.text = "\(bio)"
//created at date
let accountAge = json["created_at"] as! String
self.createdLbl.text = "\(accountAge)"
let tweetCount = json["statuses_count"] as! Int
self.tweetCount.text = "\(tweetCount)"
let likes = json["favourites_count"] as! Int
self.likesCount.text = "\(likes)"
let lists = json["listed_count"] as! Int
self.listedCount.text = "\(lists)"
}
}
}
catch let error
{
print(error)
}
}
}
}
I get an error on the second "If let" statement that says: "initializer for conditional binding must have optional type not 'Any.
Can someone explain why this is?
Your JSON is obviously a dictionary, a JSON dictionary in Swift 3 is [String:Any]
You caused the error by the silly Any annotation (which is supposed to be Any? but is practically nonsensical) because it confuses the compiler.
If you use a do block, try without question mark but use optional binding:
...
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any] {
if let immage = json["profile_image_url_https"] as? String { ...
There are a couple of problems with the syntax. [AnyObject] will not work to use reference items such as json["profile_image_url_https"]. also, you are redeclaring json through let json = json, which makes it a non option in your let immage = json?["profile_image_url_https"] call, so that becomes a problem. This structure does not have any compiler errors
if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any]
{
if let json = json, let immage = json["profile_image_url_https"] as? String
{
}
}
This does not have any compiler errors.

Resources