URLSession parameters must be valid - ios

This is the Url I am requesting for :
https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fwww.theverge.com%2Frss%2Findex.xml&api_key=u3vl3sxdva2cch7jjyrnynvwlhjycjrizhcsgmmq
If you run this on browser, it works fine and gives a JSON response. However I get this error in the catch block on running the following code : URLSession parameters must be valid :
let callURL = URL.init(string: urlString) // urlString is the above url
var request = URLRequest.init(url: callURL!)
request.addValue(ContentType_ApplicationJson, forHTTPHeaderField: HTTPHeaderField_ContentType)
request.httpMethod = HTTPMethod_Get
let dataTask = urlSession.dataTask(with: request) { (data,response,error) in
if error != nil{
completion(nil)
return
}
do {
if let resultJson = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary{
print("Result",resultJson)
if let news = resultJson.value(forKeyPath: "articles") as? [NSDictionary]{
print("News",news)
completion(news)
return
}
}
} catch {
print("Error -> \(error)")
}
}
dataTask.resume()

I am not sure what is wrong in your code but I have tested your above code in playground I am getting news below is the code
import Foundation
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let urlString = "https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fwww.theverge.com%2Frss%2Findex.xml&api_key=u3vl3sxdva2cch7jjyrnynvwlhjycjrizhcsgmmq"
let callURL = URL.init(string: urlString) // urlString is the above url
var request = URLRequest.init(url: callURL!)
request.addValue("Content-Type", forHTTPHeaderField: "application/json")
request.httpMethod = "GET"
let dataTask = URLSession.shared.dataTask(with: request) { (data,response,error) in
let res = response as! HTTPURLResponse
print(res)
if error != nil{
print(error!)
return
}
do {
if let resultJson = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary{
print("Result",resultJson)
if let news = resultJson.value(forKeyPath: "articles") as? [NSDictionary]{
print("News",news)
return
}
}
} catch {
print("Error -> \(error)")
}
}
dataTask.resume()

This worked with me
let callURL = URL.init(string: "https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fwww.theverge.com%2Frss%2Findex.xml&api_key=u3vl3sxdva2cch7jjyrnynvwlhjycjrizhcsgmmq") // urlString is the above url
var request = URLRequest.init(url: callURL!)
request.httpMethod = HTTPMethod.get.rawValue
let dataTask = URLSession.shared.dataTask(with: request) { (data,response,error) in
if error != nil{
print(error)
}
do {
if let resultJson = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary{
print("Result",resultJson)
if let news = resultJson.value(forKeyPath: "articles") as? [NSDictionary]{
print("News",news)
return
}
}
} catch {
print("Error -> \(error)")
}
}
dataTask.resume()

You don't need an URLRequest for a GET request, it's the default, just pass the URL
This works, however there is no value for key articles
let urlString = "https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fwww.theverge.com%2Frss%2Findex.xml&api_key=u3vl3sxdva2cch7jjyrnynvwlhjycjrizhcsgmmq"
let callURL = URL(string: urlString)!
let dataTask = URLSession.shared.dataTask(with: callURL) { (data,response,error) in
if error != nil { return }
do {
if let resultJson = try JSONSerialization.jsonObject(with: data!) as? [String:Any] {
print("Result",resultJson)
// if let news = resultJson["articles"] as? [[String:Any]] {
// print("News",news.count)
// return
// }
}
} catch {
print("Error -> \(error)")
}
}
dataTask.resume()
And – as always – do not use NSDictionary and valueForKey in Swift and .allowFragments is pointless if the root object is a collection type.

Related

Using POST request in HTTP method holds the UI?

When I tap on button it will perform a service request operation.Based on the result it will redirect to next view controller.
After loading Next view controller holds or block the UI. How to solve this issue ? I am using RestAPI and GCD first time in swift, so don't know how to solve this.....
This is login button
#IBAction func btnLogin(_ sender: Any)
{
self.api()
}
This is the function what we call.
func api()
{
let myURL = URL(string: "http://www.digi.com/laravel_api_demo/api/demoapipost")
let request = NSMutableURLRequest(url: myURL!)
request.httpMethod = "POST"
let strEmail = tfLgnID.text
let strPwd = tfPwd.text
let postString = ["username":strEmail, "password":strPwd]
//let postString = ["username":"ayush", "password":"abc"]
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//create the session object
//let session = URLSession.shared
do {
request.httpBody = try JSONSerialization.data(withJSONObject: postString, options: .prettyPrinted) // pass dictionary to nsdata object and set it as request body
print("Successfully passed data to server")
} catch let error {
print(error.localizedDescription)
}
let postTask = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
guard error == nil else {
return
}
guard let data = data else {
return
}
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print("POST Method :\(json)")
let dict = json as? [String: Any]
let num = dict!["status"]
print("Status : \(num)")
print("Dict : \(dict)")
print("username : \(dict!["username"])")
print("password : \(dict!["password"])")
if dict!["status"] as! Int == 1
{
print("Successfully Logged In")
DispatchQueue.main.async {
let visitorVC = self.storyboard?.instantiateViewController(withIdentifier: "VisitorVC") as! VisitorVC
self.present(visitorVC, animated: true, completion: nil)
}
print("OK")
}
else
{
print("Not OK")
}
// handle json...
}
} catch let error {
print(error.localizedDescription)
}
}
postTask.resume()
}
Try this method
func api() {
var request = URLRequest(url: URL(string: "")!) // put your url
request.httpMethod = "POST"
let strEmail = tfLgnID.text
let strPwd = tfPwd.text
let postString:String = "user_id=\(strEmail)&user_id=\(strPwd)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(String(describing: error))")
return
}
do {
if let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary {
print(jsonResult)
let status = jsonResult["status"]! as! NSString
print("status\(status)")
DispatchQueue.main.async(execute: {
// your error Alert
})
}
else {
DispatchQueue.main.async(execute: {
let visitorVC = self.storyboard?.instantiateViewController(withIdentifier: "VisitorVC") as! VisitorVC
self.present(visitorVC, animated: true, completion: nil)
})
}
}
} catch let error as NSError {
print(error.localizedDescription)
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(String(describing: responseString))")
}
task.resume()
}

error at getting image from url?

let defaultConfiguration = URLSessionConfiguration.default
let operationQueue = OperationQueue.main
let defaultSession = URLSession(configuration: defaultConfiguration, delegate: self, delegateQueue: operationQueue)
if let url = URL(string: "https://newsapi.org/v1/articles?source=abc-news-au&sortBy=top&apiKey=47d2ce48babd47b1bc391b426b89ca23")
{
(defaultSession.dataTask(with: url) { (data, response, error) in
if error != nil{
return
}
do {
let resultJson = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject]
if var dataDictionary = resultJson {
// dataDictionary["access_token"] as AnyObject
self.dataArray = dataDictionary["articles"] as! [Any]
var dataDictionary22 = self.dataArray[0] as! [String: Any] as [String : AnyObject]
let url = URL(string:
"\(String(describing: dataDictionary22["urlToImage"]!))")
print("url -> \(String(describing: url!))")
let task = URLSession.shared.dataTask(with: url!) { data, response, error in
guard let data = data, error == nil else {
return
}
self.imageView.image = UIImage(data: data)
}
task.resume()
}
} catch {
print("Error -> \(error)")
}
}).resume()
}
i am trying to get news updates from open api through nsurlsession and it has dictionary->array->dictionary->at key "urlToImage"
but iam getting url like http://www.abc.net.au/news/image/8968140-1x1-700x700.jpg but not getting image file in data it was empty can any one minimige the code lenth and solve my problem
Using this piece of code, you can parse that specific URL response successfully, I have tested it in a Playground.
This: "\(String(describing: dataDictionary22["urlToImage"]!))" is not the way get a String from an AnyObject, you should use conditional casting.
if let url = URL(string: "https://newsapi.org/v1/articles?source=abc-news-au&sortBy=top&apiKey=47d2ce48babd47b1bc391b426b89ca23"){
URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
guard error == nil, let data = data else {
print(error!);return
}
guard let resultJson = (try? JSONSerialization.jsonObject(with: data)) as? [String:Any] else {
return
}
print(resultJson)
guard let articles = resultJson["articles"] as? [[String:Any]], let firstArticle = articles.first else { return }
guard let imageUrlString = firstArticle["urlToImage"] as? String, let imageUrl = URL(string: imageUrlString) else { return }
URLSession.shared.dataTask(with: imageUrl, completionHandler: { data, response, error in
guard error == nil, let data = data else {
print(error!);return
}
let image = UIImage(data: data)
DispatchQueue.main.async {
self.imageView.image = image
}
}).resume()
}).resume()
}
If you want to get all article pictures (in your question you were only parsing the first one), just change guard let articles = resultJson["articles"] as? [[String:Any]], let firstArticle = articles.first else { return } to the following:
for article in articles {
guard let imageUrlString = article["urlToImage"] as? String, let imageUrl = URL(string: imageUrlString) else { return }
URLSession.shared.dataTask(with: imageUrl, completionHandler: { data, response, error in
guard error == nil, let data = data else {
print(error!);return
}
let image = UIImage(data: data)
//use the image
}).resume()
}

HTTP request in swift 3 Xcode 8.3

I am getting stuck with HTTP request.it did not show any error.compiler reads the first two lines and skip the code to "task.resume()".i am fetching data with same code on other view controller but it creats problem here
func getCustomers()
{
let url = NSURL(string: "myURL.com")
let task = URLSession.shared.dataTask(with: url! as URL) {
(data, response, error) in
guard let _:Data = data, let _:URLResponse = response , error == nil else {
print("error: \(String(describing: error))")
return
}
do
{
self.getcustomersArray = [GetCustomers]()
//JSON Parsing
if let data = data,
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any]
{
let results = json["Result"] as? [[String : Any]]
let getCustomersObject:GetCustomers = GetCustomers()
for result in results!
{
getCustomersObject.ActivityPrefix = (result["ActivityPrefix"] as? String)!
getCustomersObject.CustomerID = (result["CustomerID"] as? String)!
getCustomersObject.CustomerName = (result["CustomerName"] as? String)!
getCustomersObject.TFMCustomerID = (result["TFMCustomerID"] as? String)!
getCustomersObject.ShortName = (result["ShortName"] as? String)!
getCustomersObject.UserRights = (result["UserRights"] as? Int)!
self.totalCustomers += self.totalCustomers
}
self.customerName = getCustomersObject.CustomerName
}
}//end Do
catch
{
}
}
task.resume()
}
Using Block GET/POST/PUT/DELETE:
let request = NSMutableURLRequest(url: URL(string: "Your API URL here" ,param: param))!,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval:"Your request timeout time in Seconds")
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers as? [String : String]
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest) {data,response,error in
let httpResponse = response as? HTTPURLResponse
if (error != nil) {
print(error)
} else {
print(httpResponse)
}
DispatchQueue.main.async {
//Update your UI here
}
}
dataTask.resume()
I think you dont mention line
request.httpMethod = "GET"

Parse JSON response with Swift 3

I have JSON looking like this:
{"posts":
[
{
"id":"1","title":"title 1"
},
{
"id":"2","title":"title 2"
},
{
"id":"3","title":"title 3"
},
{
"id":"4","title":"title 4"
},
{
"id":"5","title":"title 5"
}
],
"text":"Some text",
"result":1
}
How can I parse that JSON with Swift 3?
I have this:
let url = URL(string: "http://domain.com/file.php")!
let request = URLRequest(url: url)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print("request failed \(error)")
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: String], let result = json["result"] {
// Parse JSON
}
} catch let parseError {
print("parsing error: \(parseError)")
let responseString = String(data: data, encoding: .utf8)
print("raw response: \(responseString)")
}
}
task.resume()
}
Use this to parse your data:
let url = URL(string: "http://example.com/file.php")
URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
guard let data = data, error == nil else { return }
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]
let posts = json["posts"] as? [[String: Any]] ?? []
print(posts)
} catch let error as NSError {
print(error)
}
}).resume()
Use guard to check if you have data and that error is empty.
Swift 5.x version
let url = URL(string: "http://example.com/file.php")
URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
guard let data = data, error == nil else { return }
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String:Any]
let posts = json?["posts"] as? [[String: Any]] ?? []
print(posts)
} catch {
print(error)
}
}).resume()
In swift 3.0 for GET method:
var request = URLRequest(url: URL(string: "Your URL")!)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(String(describing: responseString))")
}
task.resume()
In swift 3.0 for POST method:
var request = URLRequest(url: URL(string: "Your URL")!)
request.httpMethod = "POST"
let postString = "user_name=ABC" // Your parameter
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(String(describing: responseString))")
}
task.resume()
Because your data structure of test json should be "[String: AnyObject]". The json key "posts" value is Array type.
DISTANCE--DIFFICULT API
========================>
class ViewController: UIViewController {
var get_data = NSMutableData()
var get_dest = NSArray()
var org_add = NSArray()
var row_arr = NSArray()
var ele_arr = NSArray()
var ele_dic = NSDictionary()
var dist_dic = NSDictionary()
var dur_dic = NSDictionary()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
getmethod()
}
func getmethod()
{
let url_str = 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 url_req = URLRequest(url: url_str!)
let task = URLSession.shared.dataTask(with: url_req) { (data, response, error) in
if let my_data = data
{
print("my data is----->",my_data)
do
{
self.get_data.append(my_data)
let jsondata = try JSONSerialization.jsonObject(with: self.get_data as Data, options: [])as! NSDictionary
print("json data is--->",jsondata)
self.get_dest = jsondata.object(forKey: "destination_addresses")as! NSArray
let get_dest1:String = self.get_dest.object(at: 0) as! String
print("destination is--->",get_dest1)
self.org_add = jsondata.object(forKey: "origin_addresses")as! NSArray
let get_org:String = self.org_add.object(at: 0)as! String
print("original address is--->",get_org)
self.row_arr = jsondata.object(forKey: "rows")as! NSArray
let row_dic = self.row_arr.object(at: 0)as! NSDictionary
self.ele_arr = row_dic.object(forKey: "elements")as! NSArray
self.ele_dic = self.ele_arr.object(at: 0)as! NSDictionary
self.dist_dic = self.ele_dic.value(forKey: "distance")as! NSDictionary
print("distance text is--->",self.dist_dic.object(forKey: "text")as! String)
print("distance value is--->",self.dist_dic.object(forKey: "value")as! Int)
// self.ele_dic = self.ele_arr.object(at: 1)as! NSDictionary
self.dur_dic = self.ele_dic.value(forKey: "duration")as! NSDictionary
print("duration text--->",self.dur_dic.value(forKey: "text")as! String)
print("duration value--->",self.dur_dic.value(forKey: "value")as! Int)
print("status---->",self.ele_dic.object(forKey: "status")as! String)
}
catch
{
print("error is--->",error.localizedDescription)
}
}
};task.resume()
}

data is not coming JSON parsing

let url1 = "https://jsonplaceholder.typicode.com/posts"
var request = URLRequest(url: URL(string: url1)!)
request.httpMethod = "GET"
let urlSession = URLSession.shared
let task = urlSession.dataTask(with: request, completionHandler: {(data,response,error) -> Void in
if let error = error {
print(error)
return
}
if let data = data {
OperationQueue.main.addOperation({ () -> Void in
self.tableView.reloadData()
})
}
})
task.resume()
With or without http method, response data is empty. What am I doing wrong? WiFi works fine. Maybe problem on my simulator settings?
let url = URL(string: "https://jsonplaceholder.typicode.com/posts")
URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
guard let data = data, error == nil else { return }
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
let posts = json as? [[String: Any]] ?? []
print(posts)
for post in posts{
let product = Product()
product.userId = post["userId"] as! Int
product.id = post["id"] as! Int
product.title = post["title"] as! String
product.body = post["body"] as! String
self.products.append(product)
}
} catch let error as NSError {
print(error)
}
}).resume()
Yeah thanks, but your code is not works too, i mean say data is empty, nothing to be parsed. WiFi on my emulator works fine maybe problem on my xcode8?
Made some changes in your code.
let url = NSURL(string: "https://jsonplaceholder.typicode.com/posts")
NSURLSession.sharedSession().dataTaskWithRequest(NSURLRequest.init(URL: url!), completionHandler: {(data, response, error) in
guard let data = data where error == nil else { return }
do {
let posts = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
print(posts)
} catch let error as NSError {
print(error)
}
}).resume()
Output :
Here your all 100 post display

Resources