iOS | can not call URLSession function (swift 3) - ios

I am working on a student system project. All the server side things are done but the iOS client application is making some trouble.
I am trying to create a login page for the user and than check in the database whether the info is correct
Here is the code:
import Foundation
import UIKit
class LoginPage: UIViewController {
/*A reference to the username/student ID text field*/
#IBOutlet weak var idField: UITextField!
//A reference to the password field
#IBOutlet weak var passwordField: UITextField!
//Send the information from the text fields to the server
#IBAction func loginButtonTapped(_ sender: UIButton) {
//declare parameter as a dictionary which contains string as key and value combination.
var parameters = ["name": idField.text!, "password": passwordField.text!] as Dictionary<String, String>
//create the url with NSURL
let url = NSURL(string: "https://api.sis.kemoke.net")
//create the session object
var session = URLSession.sharedSession()
//now create the NSMutableRequest object using the url object
let request = NSMutableURLRequest(url: url! as URL)
request.httpMethod = "POST" //set http method as POST
var err: NSError?
request.HTTPBody = JSONSerialization.dataWithJSONObject(parameters, options: nil, error: &err) // pass dictionary to nsdata object and set it as request body
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//create dataTask using the session object to send data to the server
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()
}
}
For me this all looks good, but I am getting an error
"can not call function URLSession"
and
"Extra argument" for the error handler.
How do I fix this?

Related

Create and send json data to server using swift language and iOS 9+

I really need a code for send and receive data from server with JSON, i find a really good code but it isn't compatible with iOS9.
#IBAction func submitAction(sender: AnyObject) {
//declare parameter as a dictionary which contains string as key and value combination.
var parameters = ["name": nametextField.text, "password": passwordTextField.text] as Dictionary<String, String>
//create the url with NSURL
let url = NSURL(string: "http://myServerName.com/api") //change the url
//create the session object
var session = NSURLSession.sharedSession()
//now create the NSMutableRequest object using the url object
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST" //set http method as POST
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &err) // pass dictionary to nsdata object and set it as request body
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//create dataTask using the session object to send data to the server
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume() }
Really thanks for the help
Swift syntax changed a little bit, but not significantly to break the whole code.
You will need to adjust few things like
println(err!.localizedDescription)
to
print(err!.localizedDescription)
Then your code will compile
Maybe have a look into the Alamofire Framework.
It really is making your life easier when it comes to handling HTTP requests.
Otherwise, as vadian suggested, check out the Swift 2 (do-try-catch) Errorhandling.
I have found a great tutorial Project from deege.
https://github.com/deege/deegeu-swift-rest-example
Here a breakdown of a HTTP request.
// Setup the session to make REST GET call. Notice the URL is https NOT http!! (if you need further assistance on how and why, let me know)
let endpoint: String = "https://yourAPI-Endpoint"
let session = NSURLSession.sharedSession()
let url = NSURL(string: endpoint)!
// Make the call and handle it in a completion handler
session.dataTaskWithURL(url, completionHandler: { ( data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
// Make sure we get an OK response
guard let realResponse = response as? NSHTTPURLResponse where
realResponse.statusCode == 200 else {
print("Not a 200 response")
return
}
// Read the JSON
do {
if let jsonString = NSString(data:data!, encoding: NSUTF8StringEncoding) {
// Print what we got from the call
print(jsonString)
// Parse the JSON
let jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
let value = jsonDictionary["key"] as! String
}
} catch {
print("bad things happened")
}
}).resume()

can't cast result of JSON to an NSDictionary? How do I debug?

I have a request:
let authRequest = NSMutableURLRequest(URL: self.authUrl!)
authRequest.HTTPMethod = "POST"
var params = ["email": "me#email.com", "password": "password"] as Dictionary<String, String>
var err: NSError?
authRequest.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
authRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
authRequest.addValue("application/json", forHTTPHeaderField: "Accept")
let authSession = NSURLSession.sharedSession().dataTaskWithRequest(authRequest, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
let parsedObject: AnyObject? = NSJSONSerialization.JSONObjectWithData(data,
options: nil,
error:&err)
if let fullObject = parsedObject as? NSDictionary {
println("I am a dictionary")
} else {
println("O GOD WHY")
}
})
authSession.resume()
I'm afraid I can't show you the entirety of the data as that would provide insight into my companies authentication and user model. However, two things are worthy of note:
1) strData prints as Body:
Optional([{
2) The JSON structure is complex, containing multiple keys which map to integers, strings, objects ({}), arrays ([]) as well as arrays of objects and objects within objects.
response and data get printed out and are valid JSON, however data fails to cast to a dictionary. No error message is printed. How can I go about debugging this? Any ideas as to why this is happening?

Swift can't send URLRequest at all?

No matter what I do it seems I'm unsuccessful in sending requests. Given the below sample code I copied word for word just to see the results. Yet nothing happens, I'm really confused and need help figuring out why i can send requests fine with objective c but no matter how many variations NSURLRequest NSURLSession I try it never works on swift.
var url : String = "http://google.com?test=toto&test2=titi"
var request : NSMutableURLRequest = 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) {
println("help me")
// process jsonResult
} else {
println("hmmm")
// couldn't load JSON, look at error
}
})
DO NOT test network asynchronous requests on a commande line project.
The execution flow will stop before the asynchronousRequest terminates... You would need to add a run loop for that. Check out this link for an example.
You should take the habit to print out everything you get from a request, to understand what is going on. You can comment out everything after you are sure the request is working as expected.
var url : String = "http://google.com?test=toto&test2=titi"
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(),
completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
println("OK")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)\n\n")
println("Response: \(response)")
var err:NSError?
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: &err) as? NSDictionary
if (jsonResult != nil) {
println("jsonresult : \(jsonResult)")
// process jsonResult
} else {
println(err.debugDescription)
// couldn't load JSON, look at error
}
})
I added a line to print the NSData converted to a NSString.
Here the data is nil.
That explains the JSON parsing error.
Also, the way you create the error is not right. Check out my version to correct it.
You aren't checking for the results of your various variables. If you're trying to diagnose problems, you have to look at each critical variable. For example, first check to see if the request succeeded and if not, quit immediately. Otherwise, try parsing the JSON, showing the resulting object if successful, but showing the parsing error on failure. If the JSON parsing fails (as it will with this URL), you might even look at the string representation of the returned data.
FYI, the handling of the NSError object with NSJSONSerialization is also incorrect. It should look like:
var parsingError: NSError?
if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &parsingError) as? NSDictionary {
// success, use `jsonResult`
} else {
// failure, look at `parsingError`
}
Putting that all together:
let url = "http://google.com?test=toto&test2=titi"
let request = NSMutableURLRequest(URL: NSURL(string: url)!)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue()) {
response, data, error in
if data == nil {
println("request error: \(error)")
return
}
var parsingError: NSError?
if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &parsingError) as? NSDictionary {
println("json parsed: \(jsonResult)")
} else {
println("parsing error: \(parsingError)")
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("data: \(responseString)")
}
}
This will, with this particular URL, fail, because the response is not JSON, but this will also show you the string representation of the response.

Swift: The JSON seems alright, but I'm still getting Cocoa error 3840

I'm trying to connect into a webservice, making a post call. The JSON outputed is ok, according with jsonlint.com. The request is not being completed as I can see on my WS logs.
func create() -> Bool {
var error: NSError?
var url: NSURL = NSURL(fileURLWithPath: "\(WSUrl)/profiles.json")!
var successedOperation: Bool = false
var request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
request.HTTPMethod = "post"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var dataToJSON = "{\"profiles\":{\"email\":\"\(self.email)\",\"password\":\"\(self.password)\",\"password_confirmation\":\"\(self.passwordConfirmation)\",\"username\": \"\(self.username)\",\"age\": \"\(self.age)\",\"gender\":\"\(self.gender)\"}}"
println(dataToJSON)
request.HTTPBody = dataToJSON.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
var task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var error: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &error) as? NSDictionary
if error != nil {
println(error?.localizedDescription)
let jsonString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error: \(jsonString)")
} else {
if let parseJSON = json {
var success = parseJSON
println("Success: \(success)")
} else {
let jsonString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonString)")
}
}
})
task.resume()
return successedOperation
}
The JSON outputed is alright:
{"profiles":{"email":"diegocharles#diegocharles.com","password":"abc1234","password_confirmation":"abc1234","username": "diegocharles","age": "18","gender":"Male"}}
And the error printed
"The operation couldn’t be completed. (Cocoa error 3840.)"
fileURL(withPath:) is used to create an URL for a file on disk. What you're looking for is URL(string:).

Swift JSON cannot get second variable

I built a backend API to my app in Laravel (PHP). The return from the method I am calling (create user) is:
{"success":true,"userid":"23"}
but when accessing userid in Swift it returns a null? It can access the success variable.
Here is the code for my request:
// create the user
var request = NSMutableURLRequest(URL: NSURL(string: "http://localhost/laravel/myapi/public/createUser"))
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var params = ["username":txtUsername.text, "email":txtEmail.text, "password":txtPassword.text] as Dictionary
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
// println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
let json = NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments & .MutableLeaves, error: &err) as NSDictionary
if(err) {
println(err!.localizedDescription)
}
else {
var success = json["success"] as? Int
if(success == 1) {
var id = json["userid"] as? Int
self.lblTaken.text = "\(id)"
}
}
})
task.resume()
the println("Body: \(strData)") prints out:
Body: {"success":true,"userid":"23"}
But when trying to access the userid variable, it returns nil
Am I doing something wrong when trying to access the userid?
UPDATE
if I print out:
println(json.valueForKey("userid"))
it prints out the userid, but if I assign it to the variable, the variable returns a null still
The userId comes as a string. So, the problem is, you try to cast a string to an integer using as? and fail.
From Apple docs:
The as? operator performs a conditional cast of the expression to the specified type. The as? operator returns an optional of the specified type. At runtime, if the cast succeeds, the value of expression is wrapped in an optional and returned; otherwise, the value returned is nil. If casting to the specified type is guaranteed to fail, a compile-time error is raised. For example, casting to a type that’s neither a subclass or superclass of the type of the expression is an error.

Resources