Swift JSON Parse execution on viewLoad - ios

Im currently struggling with a small issue on my viewController. I have stored user information to hold the users logged in status, anyways when the user opens the app they are shown a "Profile" page. Im trying to (in this example return the email) return values related to that user as the app is opened but dont know how one would execute the code on the controller itself, my JSON is posted below and returns the correct needed information. However my Label will still not get the value of the users Email stored when they open the app. Label stays blank!
let myUrl = NSURL(string: "http://www.mywebsite.co.za/php/scripts/getuserEmail.php");
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST";
let postString = "user_id=\(userId)";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{
data, response, error in
println(" response = \(response)")
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("response data = \(responseString)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &err) as? NSDictionary
if let parseJSON = json
{
var userEmail = parseJSON["userEmail"] as? String
self.usersEmail.text = userEmail
}
}
Would basically like the code to execute and update my label as that view opens, as the user has the ability to change the email from another viewController already so the email should update accordingly. Any other information will gladly be provided.
Added: println to console will not execute past the assigning of the myUrl variable. The reply below will still not work however this is my full code on viewWillAppear:
override func viewWillAppear(animated: Bool) {
super.viewDidAppear(animated)
let userFirstName = NSUserDefaults.standardUserDefaults().stringForKey("userFirstName")
let userLastName = NSUserDefaults.standardUserDefaults().stringForKey("userLastName")
var userFullName = userFirstName!
userFullNameLabel.text = userFullName
let userId:String? = NSUserDefaults.standardUserDefaults().stringForKey("userId")
let imageUrl = NSURL(string:"http://www.mywebsite.co.za/profile-pictures/\(userId!)/user-profile.jpg")
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
let imageData = NSData(contentsOfURL: imageUrl!)
if(imageData != nil )
{
dispatch_async(dispatch_get_main_queue(),{
self.profilePictureImageVIew.image = UIImage(data: imageData!)
self.profilePictureImageVIew.backgroundColor = UIColor.clearColor()
})
}
}
// Send HTTP POST
let myUrl = NSURL(string: "http://www.mywebsite.co.za/php/scripts/getuserEmail.php");
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST";
let postString = "user_id=\(userId)";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{
data, response, error in
// You can print out response object
println("******* response = \(response)")
// Print out reponse body
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("****** response data = \(responseString)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &err) as? NSDictionary
if let parseJSON = json
{
var userEmail = parseJSON["userEmail"] as? String
self.usersEmail.text = userEmail
}
}
}

If I understand correctly, you're saying the page appears and your call to the web has not finished and assigned to the self.usersEmail.text yet. What I did in my project was dispatch the commands in a block like yours asynchronously on the main queue. Try doing this inside your if statement:
dispatch_async(dispatch_get_main_queue()) {
var userEmail = parseJSON["userEmail"] as? String
self.usersEmail.text = userEmail
}
Hopefully this helps. It may be improper, but hopefully somebody can let me know if it is. It works for me so far.
You also need to resume the task after its block:
let myUrl = NSURL(string: "http://www.mywebsite.co.za/php/scripts/getuserEmail.php");
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST";
let postString = "user_id=\(userId)";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{
data, response, error in
// You can print out response object
println("******* response = \(response)")
// Print out reponse body
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("****** response data = \(responseString)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &err) as? NSDictionary
if let parseJSON = json
{
var userEmail = parseJSON["userEmail"] as? String
self.usersEmail.text = userEmail
}
}
task.resume()

Thank you grdavis, marked as answer, I had however needed to change a few things to get the result I wanted and I just wanted to post the updated answer.
Moved to viewdidLoad and not viewWillAppear
When monitoring console the userID was not alone when being sent over the URL thus adding a '!' to the string fixed this too before sending the url
The resume worked
Below is my updated code, thank you again. Label updates like desired:
// Send HTTP POST
let userId:String? = NSUserDefaults.standardUserDefaults().stringForKey("userId")
let myUrl = NSURL(string: "http://www.mywebsite.co.za/php/scripts/getuserEmail.php");
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST";
let postString = "user_id=\(userId!)";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)){
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{
data, response, error in
// You can print out response object
println("******* response = \(response)")
// Print out reponse body
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("****** response data = \(responseString)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &err) as? NSDictionary
if let parseJSON = json
{
var userEmail = parseJSON["userEmail"] as? String
println("******* userEmail = \(userEmail)")
self.usersEmail.text = userEmail
}
}
task.resume()
}

Related

Taking table data located in mysql from php script into swift text view as i click a button

I'm trying to get my php script data read and parsed into the ios app and then outputted in a text view when i click the pull data button on the storyboard
import UIKit
class ViewControllerPull: UIViewController {
let URL_PULL_TEAM = "http://cgi.soic.indiana.edu/~wesmtayl/capstoneselect.php"
#IBAction func pullData(_ sender: AnyObject) {
let requestURL = NSURL(string: URL_PULL_TEAM)
let request = NSMutableURLRequest(url: requestURL! as URL)
//setting the method to post
request.httpMethod = "POST"
//creating the post parameter by concatenating the keys and values from text field
let postParameters = "username=\(username.text!)";
//adding the parameters to request body
request.httpBody = postParameters.data(using: String.Encoding.utf8)
//creating a task to send the post request
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil{
print("error is \(error)")
return;
}
//print("response = \(response!)")
//let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
//print("responseString = \(responseString!)")
let values = try! JSONSerialization.jsonObject(with: data! as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSArray
let user = values[0] as! NSDictionary
//You have to read the json in as a Dictionary after you have indexed it out of the array you read it in from

How to login by POST method or How to access data by POST method

I am trying to get data from API with multiple parameter and using Headers.
i try a lot but not success, problem is that i can do this using Alamofire. but i want to do it by NSURLSession.
func apiCalling(){
let myUrl = NSURL(string: "http://203.XXXXXXXXX.php");
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST";// Compose a query string
request.addValue("KAISAPAISA", forHTTPHeaderField: "APIXXXXX")
let postString = "uname=demo&password=demo123";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil
{
print("error=\(error)")
return
}
// You can print out response object
print("response = \(response)")
// Print out response body
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
//Let's convert response sent from a server side script to a NSDictionary object:
do {
let myJSON = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
if let parseJSON = myJSON {
// Now we can access value of First Name by its key
let firstNameValue = parseJSON["firstName"] as? String
print("firstNameValue: \(firstNameValue)")
}
} catch {
print(error)
}
}
task.resume()
}

How can i get the data from string in desired formate to have data of NSData type

func callAddWithPOST(Name mname:String, PhoneNo mphone:String, Email memail:String, Comment mcomments:String)
{
var names = [String]()
let login = ["countryId":"1"]
print("Your Result is : = \(login)")
let url = NSURL(string: "http://photokeeper.mgtcloud.co.uk/commonwebservice.asmx/getStateList")!
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: url)
do
{
let auth = try NSJSONSerialization.dataWithJSONObject(login, options: .PrettyPrinted)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
request.HTTPBody = auth
let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
let responseString = String(data:data!, encoding: NSUTF8StringEncoding)
let validresponseString = "\(responseString!)"
print(validresponseString)
let badJsonString = "This really isn't valid JSON at all"
let jsonData = validresponseString.dataUsingEncoding(NSUTF8StringEncoding)!
let badJsonData = badJsonString.dataUsingEncoding(NSUTF8StringEncoding)!
do
{
let parsed = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.AllowFragments)
let otherParsed = try NSJSONSerialization.JSONObjectWithData(badJsonData, options: NSJSONReadingOptions.AllowFragments)
}
catch let error as NSError
{
print("Done.")
}
})
task.resume()
}
catch
{
print("Error")
}
}
I am in search of one solution for fetching the desired data from this method,i want to display StateID and StateName from this string data. i can not convert the string "responseString" in NSData to have this string as NSData to fetch the desired record. Will any body please help me to fix this issue.
If you want to get the value for key from a json you should convert the json to Dictionary with this code:
Swift 3
JSONSerialization.jsonObject(with: data, options: []) as? [String:AnyObject]
Swift 2
NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String:AnyObject]
let me know in the comments if I misunderstood something before the downvote, thank you.

NSURLSession.sharedSession().dataTaskWithRequest(request) being executed last

I'm having a problem with NSURLSession.sharedSession().dataTaskWithRequest(request). I want to authenticate my app against some API and if the authentication is successful then the app will let the user to authorise health kit and finally fetch some data from there.
I have this in my viewDidLoad()
print ("AUTHORIZING APIGEE!!!")
authorizeApigee()
if (self.errorApigee == 0) {
print ("APIGEE AUTHORIZED!")
// We cannot access the user's HealthKit data without specific permission.
print ("AUTHORIZING HEALTHKIT!!")
getHealthKitPermission()
print ("HEALTHKIT AUTORIZED!")
} else {
print ("APIGEE UNAUTHORIZED!")
}
and this is the authorising function:
// Authenticating app with Apigee Health APIx
func authorizeApigee(){
// Send HTTP GET Request
let scriptUrl = "https://fhirsandbox-prod.apigee.net/oauth/v2"
let urlWithParams = scriptUrl + "/accesstoken?grant_type=client_credentials"
let myUrl = NSURL(string: urlWithParams);
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST"
// Add Basic Authorization
let username = "****"
let password = "****"
let loginString = NSString(format: "%#:%#", username, password)
let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
let base64LoginString = loginData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions())
request.setValue(base64LoginString, forHTTPHeaderField: "Authorization")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
// Check for error
if error != nil
{
self.errorApigee = 1
print("error=\(error)")
return
}
// Print out response string
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
task.resume()
}
The problem is that even though authorizeApigee() is called, the app stops at NSURLSession.sharedSession().dataTaskWithRequest(request), goes out of the function, obviously errorApigee variable is not updated and therefore it goes to the next step of authorising health kit without authorising Apigee. Finally when health kit was authorised it goes back and authorises Apigee.
Any idea why this might happen at all?
Any tip would be greatly appreciated!
This is simple example how to use completion :
func authorizeApigee(completion: (auth: Bool) -> Void) {
// Send HTTP GET Request
let scriptUrl = "https://fhirsandbox-prod.apigee.net/oauth/v2"
let urlWithParams = scriptUrl + "/accesstoken?grant_type=client_credentials"
let myUrl = NSURL(string: urlWithParams);
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST"
// Add Basic Authorization
let username = "****"
let password = "****"
let loginString = NSString(format: "%#:%#", username, password)
let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
let base64LoginString = loginData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions())
request.setValue(base64LoginString, forHTTPHeaderField: "Authorization")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
// Check for error
if error != nil
{
self.errorApigee = 1
print("error=\(error)")
completion(auth: false)
}
// Print out response string
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
completion(auth: true)
}
task.resume()
}
And how to use :
self.authorizeApigee { (auth) -> Void in
if (auth) {
getHealthKitPermission()
} else {
//print errors
}
}
NSURLSession.sharedSession().dataTaskWithRequest() is executed in another thread. It's so that the main application thread doesn't hang and wait for the request to complete. If you want a code block to run after the async task is complete, I suggest you use a completion block.
You need to use closure because api calling work in async manner so first change your function definition like this
func authorizeApigee(completion: (Int) -> ()){
let scriptUrl = "https://fhirsandbox-prod.apigee.net/oauth/v2"
let urlWithParams = scriptUrl + "/accesstoken?grant_type=client_credentials"
let myUrl = NSURL(string: urlWithParams);
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST"
// Add Basic Authorization
let username = "****"
let password = "****"
let loginString = NSString(format: "%#:%#", username, password)
let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
let base64LoginString = loginData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions())
request.setValue(base64LoginString, forHTTPHeaderField: "Authorization")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
// Check for error
if error != nil
{
completion(0)
print("error=\(error)")
return
}
// Print out response string
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
completion(1)
}
task.resume()
}
Now call your function like this
self.authorizeApigee() { (result) -> () in
if result == 0 {
print ("APIGEE AUTHORIZED!")
// We cannot access the user's HealthKit data without specific permission.
print ("AUTHORIZING HEALTHKIT!!")
getHealthKitPermission()
print ("HEALTHKIT AUTORIZED!")
} else {
print ("APIGEE UNAUTHORIZED!")
}
}

Media type is unsupported error in json post method Swift

I'm new to swift and making a simple application that converts Celsius to Fahrenheit using this : JSON WebService
My code is on a button btn action:
#IBAction func btn(sender: AnyObject) {
let celnum = txtfirld.text
let myUrl = NSURL(string: "http://webservices.daehosting.com/services/TemperatureConversions.wso");
print("pass 1")
let request = NSMutableURLRequest(URL: myUrl!);
request.HTTPMethod = "POST";
print("pass 2")
let postString = "nCelsius=\(celnum)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){
data, response, error in
print("pass 3")
if error != nil {
print("Error 1")
return
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves) as? NSDictionary
if let parseJson = json{
let resultValue = parseJson["status"] as! String!
print("result:\(resultValue)")
}
} catch {print("Error 2")}
}
task.resume()
}
But it is giving me error like this on console:
pass 1
pass 2
pass 3
responseString = Optional(The server cannot service the request because the media type is unsupported.)
Error 2
Plaese help thank u :)
1 - You should set your request Content-Type :
request.setValue(" application/json; charset=utf-8", forHeader:"Content-Type")
2 - Your body is not in JSON format, use :
let params = ["nCelscius" : 1212]
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions())

Resources