I am trying to code a login system with jSon. I can receive and parse the results but when i am trying to use values i am receiving fatal errors.
My code:
var request = NSMutableURLRequest(URL: NSURL(string: "http://www.somedomain.com/api/login.php")!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var params:NSDictionary = ["e":"\(email)", "p":"\(passwd)"]
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.allZeros, 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
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
if let parseJSON = json {
var success = parseJSON["result"] as? Int
var msg = parseJSON["msg"] as? String
println("Succes: \(success!)") // This works fine i can receive the success variable from json
if success! == 1 { // this line throws error as "fatal error: unexpectedly found nil while unwrapping an Optional value"
// Do something...
} else {
// Do something...
}
}
} else {
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()
What's the problem with my code? I can not use the values that i received from jSon in my code. I am really confused with the "Optional" thing...
When i use values in println() everything is fine, but when i use the values in code that crashes... By the way it was working fine until today :S
This is the error:
Body: Optional({"result":1,"id":"2","name":"tt","msg":"Login successfull"})
Succes: 1
fatal error: unexpectedly found nil while unwrapping an Optional value
Thanks...
Related
I have been working on this, but can't see what is wrong. The rest of my code is good but this part seems to make my program crash when I run it. When the program crashes, I get the fatal error message: "fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)"
My code is:
let barcode = metadataObj.stringValue
let token = "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
let request = NSMutableURLRequest(url:
NSURL(string:"https://example.com/api?keyword=\(barcode)&token=\(token)") as! URL)
request.httpMethod = "GET"
request.setValue("application/json;charset=utf-8", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request as URLRequest) { data, response, error -> Void in
if let data = data {
do {
print(String(data: data, encoding: String.Encoding.utf8)!)
let json = try JSONSerialization.jsonObject(with: data, options:.allowFragments) as! NSDictionary
if let items = json["items"] as? [[String: AnyObject]] {
for item in items {
let name = item["name"] as? String
let price = item["price"] as? String
let stock = item["inStock"] as? String
self.productName.text = name
self.barcodeNumber.text = barcode
self.productPrice.text = "\(price) EGP"
self.stockLabel.text = stock
}
}
}
catch let error as NSError {
print(error.localizedDescription)
}
}
else if let error = error {
print(error.localizedDescription)
}
.resume()
The HTTP GET Request results in real-life:
I am building iOS Application using Swift.I am using XCODE version 6.3.
I want to post data to server using JSON.For that i created a dictionary for performing the following operation.
//This is my dictionary right now
var parameters = ["authenticity_token":name,"platform":"mobileApp", "email": userEmail, "password": userPassword,"remember_me":"1"]
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &err)
I want to pass data as the format shown below.
{"authenticity_token":"token","platform":"mobileApp",
"user":{"email":"email_id", "password":"123456",
"remember_me":"1"}}
Right now parameter dictionary in the Format
[platform: mobileApp, authenticity_token: a1oj3olt5jn169LHn59ZbfbrBVUyov7sDVHlOl+2YzE=, email: su#gmail.com, remember_me: 1, password: samrat]
order of the paramater also changed.
I want to pass to my dictionary.
Or is there any possibility to add two dictionaries.
This is my code for posting data to server.I have another confusion whether it is correct or not.
func postData()
{
let name = defaults.stringForKey("secretKey")
var parameters = ["authenticity_token":name,"platform":"mobileApp", "email": userEmail, "password": userPassword,"remember_me":"1"]
println("Dic\(parameters)")
let url = NSURL(string: "http://behance.moblearn.net/users/sign_in")
var session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &err)
let jsonStr = NSString(data: request.HTTPBody!, encoding: NSUTF8StringEncoding)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
println("Post Method reached")
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
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
if let parseJSON = json {
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
}
else {
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()
}
I am in deep trouble.I am Beginner in swift.Help will be appreciated.
Do like this:
let innerDict = ["email": "email_id", "password": "123456", "remember_me": "1"]
let mainDict = ["authenticity_token": "token", "platform": "mobileApp", "user": innerDict]
I am retrieving datas from JSON by using swift. I am new to JSON. I don't how to retrieve this nested values. My previous question is Issue raised, while retriving datas from JSON by using swift . I got clarified. This is new to me. My JSON format is below. Kindly guide me.
JSON Response formats:
{
"salutation": {
"id": 1,
"salutation": "Mr"
},
"firstName": "AAA",
"middleName": "BBB",
"lastName": "C",
"employeeId": "RD484",
"station": {
"id": 86,
"stationCode": null,
"stationName": "DDD",
"subDivision": null,
"address": null
},
"subDivsion": {
"id": 11,
"divisionCode": "11",
"divisionDesc": "EEE",
"division": null
}
}
//My Attempt:
var maindict = NSDictionary() //Global declaration
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")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
self.maindict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as [String: AnyObject]
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)")
self.dataFromJSON() //METHOD CALLING
}
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)")
//println("AUTHENTICATION FAILED")
}
}
})
task.resume()
func dataFromJSON()
{
println("Main Dict Values: \(maindict)") //PRINTING ALL VALUES
let dataArray = maindict["firstName"] as? [String:AnyObject]
println("FirstName Values: \(dataArray)") // PRINTING NIL VALUES
}
Your data structure does not begin with an array this time, but with a Dictionary. Your structure is like is:
root Dictionary -> "salutation" -> Dictionary
root Dictionary -> "station" -> Dictionary
root Dictionary -> "subDivsion" -> Dictionary
Let's say you want to access the "id" of "salutation", then:
// Just an exemple of how to download, surely you have your own way
func getJSON(url: NSURL) {
let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: url)
let task = session.dataTaskWithRequest(request){
(data, response, downloadError) -> Void in
if let error = downloadError {
println(error.localizedDescription)
} else {
var jsonError: NSError?
// cast the result as a Dictionary
if let dict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &jsonError) as? [String: AnyObject] {
// print the dictionary to check contents
println(dict)
if let salutationDictionary = dict["salutation"] as? [String: AnyObject] {
if let id = salutationDictionary["id"] as? Int {
println(id)
}
}
}
if jsonError != nil {
println(jsonError)
}
}
}
task.resume()
}
EDIT:
My friend, your code was a mess... I suggest to you to do some cleaning when you've got errors, it helps to debug. Anyway, here's a corrected version of your new code. Pay attention to how maindict is declared on the first line. Also, you had one unnecessary call to NSJSONSerialization, I simplified it. Note: for the sake of the example, I've included your dataFromJSON function code directly inside if let parseJSON ..., but of course it doesn't mean you have to do the same.
var maindict: [String: AnyObject]?
var session = NSURLSession.sharedSession()
//let parameters = ...
let request = NSMutableURLRequest(URL: your_url!)
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, 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 err: NSError?
maindict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &err) as? [String: AnyObject]
if err != nil {
println(err!.localizedDescription)
} else {
if let parseJSON = maindict {
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
println("Main Dict Values: \(maindict)")
let firstName = maindict!["firstName"] as? String
println("FirstName: \(firstName)")
}
else {
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()
Please pay attention to the details and study my modifications by comparing with your attempt. My answer has been tested on my own server and it works, so you can use it as a working base.
The easiest way to do this is to use a library.
1) You can use swiftyJSON. It uses the objective C JSON parsing library.
https://github.com/SwiftyJSON/SwiftyJSON
2) If you want a library which uses a pure swift parser try JSONSwift. The readme on github shows how you can retrieve nested values from the JSON file. And integrating it in your project just requires you to import a single file. https://github.com/geekskool/JSONSwift
Below is my login function. It's a JSON POST request and before, when the URL was http, it worked flawlessly. I attached a JSON filled with the username/password of the user. Today we added a SSL Certificate and after switching the URL to https, it produced this error:
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9843)
I'm not really sure what's going on. I typed that error into google and didn't get any where. I appreciate any help, thank you!
func login(params : Dictionary<String, String>, url : String, postCompleted : (succeeded: Bool, msg: String) -> ()) {
var request = NSMutableURLRequest(URL: NSURL(string: url)!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
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
if response != nil {
if response.isKindOfClass(NSHTTPURLResponse) {
httpResponse = response as NSHTTPURLResponse
if let authorizationID = httpResponse.allHeaderFields["Authorization"] as String! {
Locksmith.saveData(["id":authorizationID], forUserAccount: currentUser, inService: "setUpAuthorizationId")
}
else {
println("Failed")
}
}
}
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!)'")
postCompleted(succeeded: false, msg: "Error")
}
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
if let status = parseJSON["status"] as? String {
if let extractData = parseJSON["data"] as? NSDictionary {
let extractUserId:Int = extractData["id"] as Int
userId = extractUserId
}
if status == "success" {
postCompleted(succeeded: true, msg: "Logged in.")
} else {
let failMessage = parseJSON["message"] as? String
postCompleted(succeeded: false, msg: failMessage!)
}
}
return
}
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)")
postCompleted(succeeded: false, msg: "Error")
}
}
})
task.resume()
}
Using This awesome article I was able to fix my problem. All I needed to do was add:
NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate
after my class name, and then add these two delegates:
func URLSession(session: NSURLSession,
didReceiveChallenge challenge:
NSURLAuthenticationChallenge,
completionHandler:
(NSURLSessionAuthChallengeDisposition,
NSURLCredential!) -> Void) {
completionHandler(
NSURLSessionAuthChallengeDisposition.UseCredential,
NSURLCredential(forTrust:
challenge.protectionSpace.serverTrust))
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) {
var newRequest : NSURLRequest? = request
println(newRequest?.description);
completionHandler(newRequest)
}
after that in my actual request I just needed to change:
var session = NSURLSession.sharedSession()
to:
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
var session = NSURLSession(configuration: configuration, delegate: self, delegateQueue:NSOperationQueue.mainQueue())
hope this helps someone!!
The getRequest worked out perfectly and got the code 200 response and the json data. The postRequest function didn't work and returned Error 400. Any ideas on what could be wrong? Maybe my parameters are not stated correctly?!! Thanks
func getRequest(searchString : String) {
let latitude = 44.3
let longitude = 37.2
let latLongUrl = NSURL(string: "https://api.foursquare.com/v2/venues/search?ll=\(latitude),\(longitude)&client_id=\(kFoursquareAppID)&client_secret=\(kFoursquareAppSecret)&v=20150111") //* find a way to pass the date format into the date area with the YYYYMMDD specific format
let searchQueryUrl = NSURL(string: "https://api.foursquare.com/v2/venues/search?client_id=\(kFoursquareAppID)&client_secret=\(kFoursquareAppSecret)&v=20150111&ll=\(latitude),\(longitude)&query=\(searchString)")
let searchQuery2 = NSURL(string: "https://api.foursquare.com/v2/venues/search?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&v=20130815&ll=40.7,-74&query=sushi")
//In the HTTP request, you need to pass in your client ID, client secret, a version parameter, and any other parameters that the endpoint requires:
let task2 = NSURLSession.sharedSession().dataTaskWithURL(latLongUrl!, completionHandler: { (data, response, error) -> Void in
var stringData = NSString(data: data, encoding: NSUTF8StringEncoding)
println(stringData)
println(response)
})
}
func postRequest(searchString : String) {
let latitude = 44.3
let longitude = 37.2
let latLon = "\(latitude), \(longitude)"
var request = NSMutableURLRequest(URL: NSURL(string: "https://api.foursquare.com/v2/venues/search")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
//Setup the Params Dictionary
var params = [
"ll" : latLon,
"client_id" : kFoursquareAppID,
"client_secret" : kFoursquareAppSecret,
"categoryId" : "4bf58dd8d48988d1e0931735",
"v" : "20150111"]
//Setup an Error
var error: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &error)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//Call a completion Handler when this url call is complete
var task = session.dataTaskWithRequest(request, completionHandler: { (data, respose, err) -> Void in
var stringData = NSString(data: data, encoding: NSUTF8StringEncoding)
//Convert the String into a dictionary
var conversionError: NSError?
//This is the way we can convert the data into a dictionary into those keyValue Pairs
var jsonDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableLeaves, error: &conversionError) as NSDictionary
println(jsonDictionary) //this will print out the value we are getting as a dictionary in the console.
})
task.resume()
}