I am new on Swift but I was follwoing some examples like how to make a login app sending username and password fields to a php file and getting the json response back.
When I print my responseString I get:
[{"userid":1,"username":"rodrigo","password":"minhoca","groupname":"couple"}]
But when I try to parse the json I never can set the username variable because never gets into that part of the code, I just get "here"
Thanks for the help
func sendLoginInfo(username: String, password: String) -> String{
if let url = URL(string: "myphpurl"){
let request = NSMutableURLRequest(url:url)
request.httpMethod = "POST";// Compose a query string
let postString = "?username=\(myUsername)&password=\(myPassword)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with:request as URLRequest){
data, response, error in
if error != nil{
print("1\(error)")
}
else{
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("response string = \(responseString!)")
}
do {
if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
// Print out dictionary
print(convertedJsonIntoDict)
// Get value by key
let firstNameValue = convertedJsonIntoDict["username"] as? String
print("here = \(firstNameValue!)")
}
else{
print("here")
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
task.resume()
}
return ""
}
Change the NSDictionary to NSArray in your code because you are getting an array and trying to convert to dictonary:
if let convertedJson = try JSONSerialization.jsonObject(with: data!, options: []) as? NSArray
get the object at index 0 which will give you dictonary & then you can get username
So the Final code will be:
func sendLoginInfo(username: String, password: String) -> String{
if let url = URL(string: "myphpurl"){
let request = NSMutableURLRequest(url:url)
request.httpMethod = "POST";// Compose a query string
let postString = "?username=\(myUsername)&password=\(myPassword)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with:request as URLRequest){
data, response, error in
if error != nil{
print("1\(error)")
}
else{
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("response string = \(responseString!)")
}
do {
if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data!, options: []) as? NSArray {
// Print out dictionary
print(convertedJsonIntoDict)
// Get value by key
let firstNameValue = (convertedJsonIntoDict[0] as! NSDictionary)["username"] as? String
print("here = \(firstNameValue!)")
}
else{
print("here")
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
task.resume()
}
return ""
}
Related
this is my code for the Json request to php and to show the data in the app:
import Foundation
protocol FeedmodelProtocol: class {
func itemsDownloaded(items: NSArray)
}
class Feedmodel: NSObject, URLSessionDataDelegate {
weak var delegate: FeedmodelProtocol!
func downloadItems() {
let myUrl = URL(string: "http://www.example.net/zumba.php");
var request = URLRequest(url:myUrl!)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postString = "firstName=51&lastName=6";
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))")
self.parseJSON(data)
}
task.resume()
}
func parseJSON(_ data:Data) {
var jsonResult = NSArray()
do{
jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray;
} catch let error as NSError {
print(error)
}
var jsonElement = NSDictionary()
let stocks = NSMutableArray()
for i in 0 ..< jsonResult.count
{
print(jsonResult)
jsonElement = jsonResult[i] as! NSDictionary
let stock = Stockmodel()
//the following insures none of the JsonElement values are nil through optional binding
if let Datum = jsonElement["Datum"] as? String,
let Tankstelle = jsonElement["Tankstelle"] as? String,
let Kraftstoff1 = jsonElement["Kraftstoff1"] as? String,
let Preis1 = jsonElement["Preis1"] as? String,
let Kraftstoff2 = jsonElement["Kraftstoff2"] as? String,
let Preis2 = jsonElement["Preis2"] as? String,
let Notiz = jsonElement["Notiz"] as? String,
let longitude = jsonElement["longitude"] as? String,
let latitude = jsonElement["latitude"] as? String
{
print (Datum)
print(Tankstelle)
print(Kraftstoff1)
print(Preis1)
print(Kraftstoff2)
print(Preis2)
print(Notiz)
print(longitude)
print(latitude)
stock.Datum = Datum
stock.Tankstelle = Tankstelle
stock.Kraftstoff1 = Kraftstoff1
stock.Preis1 = Preis1
stock.Kraftstoff2 = Kraftstoff2
stock.Preis2 = Preis2
stock.Notiz = Notiz
stock.longitude = longitude
stock.latitude = latitude
}
stocks.add(stock)
}
DispatchQueue.main.async(execute: { () -> Void in
self.delegate.itemsDownloaded(items: stocks)
})
}
}
I have a mySQL PHP what seems to work because my Console shows me that:
responseString = Optional("[\"51\",\"6\"]") (
51,
6 ) Could not cast value of type 'NSTaggedPointerString' (0x1045cbf68) to 'NSDictionary' (0x1045cc288). 2018-06-20
23:29:34.586355+0200 TankBilliger[37631:3753628] Could not cast value
of type 'NSTaggedPointerString' (0x1045cbf68) to 'NSDictionary'
(0x1045cc288). (lldb)
I don't know what the problem is, can anyone help?
Thank You!
The problem is , your getting data as dictionary but you taken as string
delete this line and try
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(String(describing: responseString))")
This method parseJSON() do above functionality
i want to send a url.request(POST)with a Codable Struct like That :
struct Picklist : Codable {
var id = Int()
var ean = String()
var position = String()
}
and my request is like that :
let request = NSMutableURLRequest(url: NSURL(string: "http://XXX.XX.XX.XX/NEW/index.php")! as URL)
request.httpMethod = "POST"
let myID = Picklist.init(id: 3, ean: "asdf", position: "q")
let encoder = JSONEncoder()
do {
let jsonData = try encoder.encode(myID)
request.httpBody = jsonData
print("jsonData: ", String(data: request.httpBody!, encoding: .utf8) ?? "no body data")
} catch {
print("ERROR")
}
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
}
task.resume()
and of the Server Side i have this PHP Script:
<?php
print_r($_POST);
?>
but i am receiving :
responseString = Optional(Array
(
[{"id":3,"ean":"asdf","position":"q"}] =>
)
my Problem is that i can't get the Keys with the value on my PHP..
what is wrong with the code ?
Finally, answer is :
if you want to work with the response string just go and decode the "data"
For example :
guard let data = data else {return}
do{
let realData = try JSONDecoder().decode(response.self, from: data)
completion(realData)
}catch let jsonErr{
print(jsonErr)
}
in realData you can work with the data, but you need to create Codable/decobale Struct to work with
response is my coddle/decodable struct
or :
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON)
}
I have been trying to fetch certain values from database through my postString, but it doesn't return any value. Php is tested and its working fine, any help would be appreciated. Below is the code.
import UIKit
class DisplayDetailedViewController: UIViewController {
var role = String()
var date = String()
var city = String()
var mark_ref = String()
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func getData(){
let myUrl = URL(string:"http://xxxxxx.co.in/xxxxx/show_report1.php")
var request = URLRequest(url: myUrl! as URL)
request.httpMethod = "POST"
let postString = "city=\(city)&date=\(date)&market_rep=\(mark_ref)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
DispatchQueue.main.async{
if error != nil{
print("error is\(String(describing: error))")
}
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
let myBoard : String!
myBoard = parseJSON["success"] as! String?
print(myBoard)
}
}
catch {
print(error)
}
}
}
task.resume()
}
}
Try 1: Replace below line (NSDictionary)
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
Try 2: Replace below line (NSArray)
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSArray
Try 3: Replace below line (NSString)
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSArray
Also try to options: .mutableContainers -> options: JSONSerialization.ReadingOptions.allowFragments
So I've got a few lines that will "login" to the web page, and they fetch the contents and print them to the console, but I can't figure out how to get the results out of the "task" and use them later on in the code.
let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8888/mobilelogin.php")!)
request.HTTPMethod = "POST"
let username = email_input.text;
let password = password_input.text;
var postString = "username="
postString += username!
postString += "&password="
postString += password!
print(postString);
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
print(request.HTTPBody);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in guard error == nil && data != nil
else {
// check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 {
// check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
return
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
print("responseString = \(responseString)");
return
}
print("This is the task string")
task.resume()
You can't return from a closure, you need to use a "callback".
We make a function for your code:
func getData(username username: String, password: String)
but instead of adding a return type, we add a callback, here named "completion":
func getData(username username: String, password: String, completion: (response: String)->()) {
}
And inside the function, we use this callback at the location where the data will be available:
func getData(username username: String, password: String, completion: (response: String)->()) {
let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8888/mobilelogin.php")!)
request.HTTPMethod = "POST"
var postString = "username="
postString += username
postString += "&password="
postString += password
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
guard let data = data where error == nil else {
fatalError(error!.debugDescription)
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 {
print("response = \(response)")
fatalError("statusCode should be 200, but is \(httpStatus.statusCode)")
}
guard let str = String(data: data, encoding: NSUTF8StringEncoding) else {
fatalError("impossible to get string from data")
}
completion(response: str)
}
task.resume()
}
And you will use it like this:
getData(username: email_input.text!, password: password_input.text!) { (response) in
print(response)
}
I can see this question has been asked before but can't find that anyone has accepted an answer anywhere. My error is:
NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.
let myUrl = NSURL(string: "http://www.example.com/xxx.php")
let request = NSMutableURLRequest(URL:myUrl!);
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST";
let postString = "email=\(useremail)&pass=\(userpassword)&username=\(username)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = session.dataTaskWithRequest(request) { (data, response, error) in
// if error
if error != nil {
print("error=\(error)")
return
}
var json: NSDictionary? = nil
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
} catch {
print("error=\(error)")
}
if let parseJSON = json {
let resultvalue = parseJSON["status"] as? String
print("result: \(resultvalue)")
var isuserregistered:Bool = false;
if(resultvalue=="Success") { isuserregistered = true; }
var messagetodisplay:String = parseJSON["message"] as! String!;
if(!isuserregistered)
{
messagetodisplay = parseJSON["message"] as! String!;
}}
I am trying to send email, pass, username, and successfully presenting my alert and changing view controller. but I am yet to hit database. It's PHP and MYSQL via url.
try changing this line
json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
to this
json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments) as? NSDictionary