I have this code:
let urls : String = Baseurl+"lat="+latitude+"&lon="+longitude+"&APPID="+apiKey
if let url = NSURL(string: urls) {
do {
let jsonResult = try NSString(contentsOfURL: url, usedEncoding: nil)
do {
if let jsonRes = try NSJSONSerialization.JSONObjectWithData(jsonResult, options: []) as? NSDictionary {
print(jsonRes)
}
} catch let error as NSError {
print(error.localizedDescription)
}
But there is an error on this line: if let jsonRes = try.... The error is: cannot convert value of type 'NSString' to expected argument type 'NSData'.
When I print the jsonResult I get this:
{
"coord":{
"lon":-0.13,
"lat":51.51
},
"weather":[
{
"id":501,
"main":"Rain",
"description":"moderate rain",
"icon":"10d"
}
],
"base":"stations",
"main":{
"temp":284.46,
"pressure":1023,
"humidity":76,
"temp_min":283.15,
"temp_max":285.15
},
"visibility":10000,
"wind":{
"speed":7.7,
"deg":220
},
"clouds":{
"all":75
},
"dt":1449755400,
"sys":{
"type":1,
"id":5093,
"message":0.0414,
"country":"GB",
"sunrise":1449734113,
"sunset":1449762690
},
"id":2643743,
"name":"London",
"cod":200
}
How can I acces those values?
NSJSONSerialization.JSONObjectWithData() expects an NSData object, not a String.
Replace
let jsonResult = try NSString(contentsOfURL: url, usedEncoding: nil)
with
let jsonResult = NSData(contentsOfURL: url)
and remove the try.
I should also note that this isn't really the best way to make a web request, you should use NSURLSession to make an async request:
NSURLSession().dataTaskWithURL(NSURL(string: urls)!) { (data, response, error) -> Void in
if let data = data {
do {
let dict = try NSJSONSerialization.JSONObjectWithData(data, options: [])
print(dict)
} catch {
print(error)
}
}
}.resume()
Related
I am try to get my UILabel text to equal the url text I am not getting any errors but it just is not doing anything not sure what I am doing wrong?
let tasks = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print("error")
} else {
if let content = data {
do {
let Json = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
if let data = Json as? NSString {
DispatchQueue.main.async {
self.myLabel.text = "\(data)"
}
}
} catch {
}
}
}
}
tasks.resume()
Your API Response is not String , It's Dictionary Dictionary in json is {}
API Response:
{
quote: "Travel is the most private of pleasures. There is no greater bore than the travel bore. We do not in the least want to hear what he has seen in Hong Kong.",
author: "Vita Sackville-West",
cat: "travel"
}
so you will not pass this condition at this line if let data = Json as? NSString because data is Dictionary not String
Correct solution :
let tasks = URLSession.shared.dataTask(with: URL(string: "https://talaikis.com/api/quotes/random/")!) { (data, response, error) in
if error != nil {
print("error")
} else {
if let content = data {
do {
let Json = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
if let data = Json as? [AnyHashable:Any] {
if let quote = data["quote"] as? String {
print(quote)
}
if let author = data["author"] as? String {
print(author)
}
if let cat = data["cat"] as? String {
print(cat)
}
DispatchQueue.main.async {
self.myLabel.text = "\(quote)"
}
}
} catch {
}
}
}
}
tasks.resume()
}
I am trying to create a callback on swift 3 but haven't had any luck so far. I was taking a look at this question: link which is similar, but the answer gives me an error.
Basically I have an API struct with a static function that I need to have a callback.
import UIKit
struct API {
public static func functionWithCallback(params: Dictionary<String, String>, success: #escaping ((_ response: String) -> Ticket), failure: #escaping((_ error:String) -> String) ) {
let app_server_url = "http://api.com" + params["key"]!
let url: URL = URL(string: app_server_url)!
var request: URLRequest = URLRequest(url: url)
request.httpMethod = "POST"
do {
request.httpBody = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
request.addValue("application/json charset=utf-8", forHTTPHeaderField: "Content-Type")
request.addValue("application/json charset=utf-8", forHTTPHeaderField: "Accept")
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {
return
}
guard let data = data else {
return
}
DispatchQueue.main.async {
do {
let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
print(json)
var message = ""
if let result = json["result"] as? String {
if(result == "success") {
//attempt to call callback gives me an error: extra argument in call
success("") {
let ticket = json["ticket"] as! NSDictionary
var date = ticket["date"] as! String
var ticket: Ticket = nil
ticket.setDate(date: date)
return ticket
}
}
else {
message = json["message"] as! String
print(message)
}
} catch let error {
print(error.localizedDescription)
let description = error.localizedDescription
if let data = description.data(using: .utf8) {
do {
let jsonError = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
let message = jsonError?["message"] as! String
} catch {
}
}
}
}
})
task.resume()
}
}
So I basically can't call the callback success because it gives me an error: Extra argument in call. Any idea on how to fix it?
My goal is to call:
API.functionWithCallback(params: params, success() -> Ticket {
//do something with the returned ticket here
},
error() -> () {
//do something with the error message here
}
)
I believe you have it wrong on how to use call back closures, from what I can understand of your question you want to do something with the ticket in the call back closure and to do that it should be a parameter of the closure not the return type of the closure.
Replace your function declaration with this:
public static func functionWithCallback(params: Dictionary<String, String>, success: #escaping ((_ response: String, _ ticket: Ticket) -> Void), failure: #escaping((_ error:String) -> Void) ) {
And inside the function replace this:
success("") {
let ticket = json["ticket"] as! NSDictionary
var date = ticket["date"] as! String
var ticket: Ticket = nil // Im not sure what you are trying to do with this line but this will definitely give an error
ticket.setDate(date: date)
return ticket
}
With:
let ticket = json["ticket"] as! NSDictionary
var date = ticket["date"] as! String
var ticket: Ticket = nil // fix this line
ticket.setDate(date: date)
success("",ticket)
And then you can call the function like this:
API.functionWithCallback(params: params, success: { response, ticket in
// you can use ticket here
// and also the response text
}) { errorMessage in
// use the error message here
}
Try this :
func uploadImage(api: String,token : String, methodType : String, requestDictionary: [String:AnyObject],picData:[Data], successHandler: #escaping (AnyObject) -> Void,failureHandler: #escaping (NSError) -> Void)
{
if Common_Methods.Reachability1.isConnectedToNetwork() == false
{
let del :AppDelegate = (UIApplication.shared.delegate as? AppDelegate)!
let nav : UINavigationController = (del.window?.rootViewController as? UINavigationController)!
let alert = UIAlertController(title: "", message: "The Internet connection appears to be offline" , preferredStyle: UIAlertControllerStyle.alert)
// Create the actions
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default)
{
UIAlertAction in
}
alert.addAction(okAction)
nav.present( alert, animated: true, completion: nil)
return
}
let apiUrl = "\(KbaseUrl)\(api)"
let session = URLSession.shared
let url: NSURL = NSURL(string: apiUrl as String)!
print(url)
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = methodType
let boundary = NSString(format: "---------------------------14737809831466499882746641449") as String
//-------- add token as perameter and set a check if token not nill then set token in header -------
if(token.characters.count > 0)
{
request.setValue(token, forHTTPHeaderField: "x-logintoken")
}
request.setValue("Keep-Alive", forHTTPHeaderField: "Connection")
request.setValue("multipart/form-data; boundary="+boundary, forHTTPHeaderField: "Content-Type")
let data = createBodyWithParameters(parameters: requestDictionary, filePathKey:nil, imageDataKey: picData.count > 0 ? picData : [], boundary: boundary)
print(data)
request.httpBody = data
let task = session.dataTask(with: request as URLRequest) { data, response, error in
// handle fundamental network errors (e.g. no connectivity)
guard error == nil && data != nil else {
successHandler(data as AnyObject )//completion(data as AnyObject?, error as NSError?)
print(error)
DispatchQueue.main.async {
Common_Methods.hideHUD(view: (topVC?.view)!)
}
return
}
// check that http status code was 200
if let httpResponse = response as? HTTPURLResponse , httpResponse.statusCode != 200 {
do {
let responseObject = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary
if let responseDictionary = responseObject as? [String:AnyObject]
{
if responseDictionary["statusCode"] as! Int == 401
{
// self.objDelegate.sessionExpire(msgStr: "Session Expired. Please login again to continue.")
}
else
{
//completion(String(data: data!, encoding: String.Encoding.utf8) as AnyObject?, nil)
}
}
} catch let error as NSError {
print(error)
DispatchQueue.main.async {
Common_Methods.hideHUD(view: (topVC?.view)!)
}
// completion(String(data: data!, encoding: String.Encoding.utf8) as AnyObject?, nil)
}
}
// parse the JSON response
do {
DispatchQueue.main.async {
Common_Methods.hideHUD(view: (topVC?.view)!)
}
let responseObject = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary
successHandler(responseObject! )
} catch let error as NSError {
DispatchQueue.main.async {
Common_Methods.hideHUD(view: (topVC?.view)!)
}
// completion(String(data: data!, encoding: String.Encoding.utf8) as AnyObject?, error)
failureHandler(error)
}
}
task.resume()
// return task
}
and function Call is :
WebService.sharedInstance.uploadImage(api: KEditEmployerProfile,token: token,methodType: "PUT", requestDictionary: parameters1 as! [String : AnyObject], picData: [imageData as Data], successHandler: { (responseObject) in
print(responseObject)
}) { (error) in
print(error)
}
}
i tried to get The (Name) value to a label
i used resultLabel.text = !(jsonResult["name"]) but it returns an error
Cannot subscript a value of type 'AnyObject' with an index of type 'String'
See my JSON
and does anybody know's how to get the data..
My code ....
if let url = URL(string: "http://www.omdbapi.com/?t=The+Raid&y=&plot=short&r=json") {
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in // URLSession.shared().dataTask(with: url) { (data, response, error) is now URLSession.shared.dataTask(with: url) { (data, response, error)
if error != nil {
print(error)
} else {
if let urlContent = data {
do {
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject // Added "as anyObject" to fix syntax error in Xcode 8 Beta 6
print(jsonResult)
print(jsonResult["Title"])
resultLabel.text = (jsonResult["name"])
if let description = ((jsonResult["weather"] as? NSArray)?[0] as? NSDictionary)?["description"] as? String {
DispatchQueue.main.sync(execute: {
self.resultLabel.text = description
})
}
} catch {
print("JSON Processing Failed")
}
}
}
}
task.resume()
} else {
resultLabel.text = "Couldn't find weather for that city - please try another."
}
}
Casting the result of JSON deserialization to AnyObject is the worst you can do.
First of all the unspecified JSON type is Any and since the type is supposed to be a dictionary, cast it to [String:Any].
Further in Swift 3 the compiler must know all types which are subscripted
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: []) as! [String:Any]
let name = jsonResult["name"] as? String
print(name ?? "n/a")
if let weather = jsonResult["weather"] as? [[String:Any]], !weather.isEmpty {
if let description = weather[0]["description"] as? String {
DispatchQueue.main.async { // not sync !!
self.resultLabel.text = description
}
}
...
PS: As always, mutableContainers is meaningless in Swift and meaningless anyway if the values are only read.
I want to cast jsonResult to NSDicitonary to be able to do a callback of jsonResult. Is this possible?
func request(url:String,callback:(NSDictionary)->()) {
let nsURL = NSURL(string: url)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(nsURL!, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error)
} else {
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
print(jsonResult[0])
} catch {
print("my error")
}
}
})
If I understand your question, you can use optional binding to cast your object:
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSArray {
if let dict = jsonResult[0] as? NSDictionary {
callback(dict)
}
}
I have a database created in Cloudant and I am trying to parse that data in my Swift project. I have imported the Cloudant libraries, but I am not able to parse the data.
Here is the code that I Have been using till now
var url = "https://username:password#cloudant.com/dashboard.html#/database/db_2/login_details"
var request = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if jsonResult != nil {
if let item = json[0] {
if let student_name = item["Student_name"] {
if let pasword = student_name["password"] {
println("Login Successfull")
}
}
}
}
}
Can somebody tell me where am I going wrong?
You should use stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) to convert any special characters your link may have. Also NSURL may return nil so you need to use if let to handle it as follow :
if let link = "https://username:password#cloudant.com/dashboard.html#/database/db_2/login_details".stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
if let checkedUrl = NSURL(string: link) {
println("valid Url")
// your code
} else {
println("invalid Url")
}
}