I am having trouble using URLSession to access JSON data generated by a PHP file.
I am both confused about the Swift 3 syntax and the completion handlers.
So far I have:
override func viewDidLoad() {
super.viewDidLoad()
var data : NSMutableData = NSMutableData()
let urlString: String = "http://seemeclothing.xyz/service.php"
let urlObject: URL = URL(string: urlString)!
let response = URLResponse
let config = URLSessionConfiguration.default
let sessionObject: URLSession
sessionObject.dataTask(with: urlObject) { (Data?, URLResponse?, Error?) in
print(data)
print(URLResponse)
print(Error)
}
sessionObject.resume()
}
I want sessionObject to go to my server and print JSON data from PHP file.
Any help would be greatly appreciated.
I would strongly suggest using Alamofire. It abstracts away all the tedious stuff in URLSession. I switched to this a few days ago and am a happy camper since then.
For your problem:
Alamofire.request("https://httpbin.org/get").responseJSON { response in
print(response.request) // original URL request
print(response.response) // HTTP URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
Related
Hi all I am trying my hands on Swift and I am trying to post users registration data. I know how to do it firebase but my main project is in php mysql so I want to connect it with swift
#IBAction func signUp(_ sender: Any) {
//check textfield data
checkTextFields()
//create user
let url = NSURL(string: "http://localhost:8888/helo/register.php")
let request = NSMutableURLRequest(url: url! as URL)
request.httpMethod = "POST"
//apending body to url
let body = "Fullname=\(name.text!.lowercased())&userName=\(userName.text!.lowercased())&emailAddress=\(emailAddress.text!.lowercased())&password=\(password.text!.lowercased())"
request.httpBody = body.data(using: String.Encoding.utf8)
//lunching
URLSession.shared.dataTaskWithRequest(request as URLRequest, completionHandler: { (data:NSData?, response:URLResponse?, error:NSError?) in
if error == nil{
dispatch_async(dispatch_get_main_queue(),{
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as?
NSDictionary
guard let parseJSON = json else{
print("Error while parsing")
return
}
let id = parseJSON["id"]
if id != nil {
print(parseJSON)
}
}catch{
print("Caugth an error: \(error)")
}
})
}else{
print("error: \(error)")
}
} )
}
I am getting an error on the line where I have commented as as lunching which say
Cannot convert value of type '(NSData?, URLResponse?, NSError?) -> ()' to expected argument type '(Data?, URLResponse?, Error?) -> Void'
I am new to Swift any help is welcome thank you all. I am using Xcode 9
After enough reading, I just realised I was doing a very tedious and using orthodox method when things have improved. I removed the whole code and did everything with Alamofire. Its really easy and straight forward. I will post the code below to help others who encounter similar problems later on.
//Constant that holds the URL for our web servicer
let URL_USER_REGISTER = "http://localhost:8888/members/register.php?"
Alamofire.request(URL_USER_REGISTER, method: .post, parameters: parameters).responseJSON{
response in
//printing response
print(response)
//getting json value from the server
if let result = response.result.value {
//converting it as NSDictionary
let jsonData = result as! NSDictionary
//displaying the message in label
self.lableMessage.text = jsonData.value(forKey: "message") as! String?
}
}
you have to first import Alamofire.
I'm currently on a project where I have to submit some data to PHP file and get the return from PHP.
Problem
When I try to do that using iOS URLSession, I'm getting an error,
The data couldn’t be read because it isn’t in the correct format.
Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set."
UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
Because of this error, I made a sample php file where I return the value which I sent from Swift. And still getting this error along with some additional information.
<NSHTTPURLResponse: 0x60400042e200> { URL: http://192.168.1.99/insertDataTest.php } { status code: 200, headers {
Connection = "Keep-Alive";
"Content-Length" = 5;
"Content-Type" = "application/json";
Date = "Thu, 07 Dec 2017 09:55:58 GMT";
"Keep-Alive" = "timeout=5, max=100";
Server = "Apache/2.4.10 (Raspbian)";
} }
What I've done so far
Here I know the content coming from the PHP, cannot be read by Swift.
I'm sending a 5 digit string from Swift to PHP and since I'm returning it without doing anything, I'm getting length of 5 data. Also I manually added a code to php in orders to made header as application/json. But still getting this error. I'm sending json encoded data from PHP as well.
My Code
Swift:
let postParameters = "{\"usermobilenum\":12345}"
request.httpBody = postParameters.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest)
{
data, response, error in
if error != nil
{
print("error is \(String(describing: error))")
return;
}
do
{
print(response!)
let myJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = myJSON
{
var msg : String!
msg = parseJSON["message"] as! String?
print(msg)
}
}
catch
{
print(error.localizedDescription)
print(error)
}
}
task.resume()
PHP :
<?php
header("Content-Type: application/json");
if($_SERVER["REQUEST_METHOD"]=="POST")
{
$data =json_decode(file_get_contents('php://input'),true);
$userPhone = $data["usermobilenum"];
echo json_encode($userPhone);
mysqli_close($connect);
}
else
{
echo json_encode("Failed in POST Method");
}
?>
I have no idea what this causes. I did try to find a solution for this in the internet and had no luck. Please help here. I'm using the latest Swift version.
Luckily I found the solution for my own problem. I missed to understand the error. As it says "option to allow fragments not set.", What I did was adding option .allowFragments. So the whole line after this replacement,
let myJSON = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
And I could solve the problem and get the answer PHP returns.
guys, i am having problem of posting json data through alamofire 4 with swift3 and also the problem of retrieving the json data at XAMPP server side using php.
My swift 3 code did trigger the php script at XAMPP, but somehow i can't get it through $_POST variable in php
Here is my code,
func uploadImage(image: UIImage){
//Now use image to create into NSData format
let imageData:NSData = UIImagePNGRepresentation(image)! as NSData
//convert the nsdata to base64 encoded string
let strBase64:String = imageData.base64EncodedString(options: .lineLength64Characters)
// let parameters = ["image": strBase64] as Dictionary
let parameters = ["image": strBase64]
print(strBase64)
Alamofire.request("http://localhost/Test/api/UploadPhoto.php",method: .post, parameters: parameters, encoding: JSONEncoding.default).response { response in
print(response)
}
}
Here is my server side code(the script did get triggered by the call from alamofire, but somehow i just can't get the data through calling$_POST["image"])
<?php
//scripts below did get triggered, but can't get the json data through calling $_POST["image"];
$imageString = $_POST["image"];
$filename_path = md5(time().uniqid()).".png";
$data = base64_decode($imageString);
file_put_contents('../AllImages/'.$filename_path, $data);
echo json_encode($_POST["image"]);
?>
if possible, please help me, i have been struggled for nearly a week, but can't find many clues
Thank you
i have found a way to solve this problem, basically, i used urlsession.shared.datatask to help me instead of alamofire with the post request,
here is my ios side code
func uploadImage(image: UIImage, completionHandler: #escaping (String) ->()){
// Now use image to create into NSData format
let imageData:NSData = UIImagePNGRepresentation(image)! as NSData
//convert the nsdata to base64 encoded string
let strBase64:String = imageData.base64EncodedString(options: .lineLength64Characters)
// prepare json data
let json: [String: Any] = ["image": strBase64]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
// create post request
let url = URL(string: "http://10.10.10.72/Test/api/UploadPhoto.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// insert json data to the request
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
do {
guard let data = data else {
throw JSONError.NoData
}
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject] else {
throw JSONError.ConversionFailed
}
completionHandler(json["sign"] as! String)
} catch let error as JSONError {
print(error.rawValue)
} catch let error as NSError {
print(error.debugDescription)
}
}
task.resume()
}
i used dictionary to store my data, and converted it to json data format to be sent to server
let json: [String: Any] = ["image": strBase64]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
Then at the php side, i retrieved it by using
$entityBody = file_get_contents('php://input');
, then i decoded from json which produced me an array and i can access my value by referencing image, so full php side of code as below:
<?php
//get the posted json data
$entityBody = file_get_contents('php://input');
//decode the json data
$decoded = json_decode($entityBody, TRUE);
$imageString = $decoded["image"];
//create a unique name for the image
$filename_path = md5(time().uniqid()).".png";
//converted the image string back to image
$data = base64_decode($imageString);
//put it on the desired location
file_put_contents('../AllImages/uploads/signature/'.$filename_path, $data);
$response = array();
//create the response
$response['sign'] = '../AllImages/uploads/signature/'.$filename_path;
echo json_encode($response);
?>
do note here, i encode the json data again to be sent back as a response from php to my ios side, and you need to decode the response from json, so the full idea is if you encode the value to json from one side, you need to decode it from another side to access the value properly, correct me if i am wrong, i am glad that my app is up and running now with all the requests now :D
I know this question has been asked dozens of times before but unfortunately I'm not knowledgable enough with Swift to adapt those answers to my issue.
Basically I have a function that sends a POST request to a php script on a server but the response seems to take longer to receive than it does for my script to utilise the result. It sends a number variable and receives one as a response so I am also converting it from an 'any_object' to an 'NSNumber'.
From what I understand I need to implement a completion handler but I can't seem to figure out how to get it to work with my code below.
var dataResult: Int = 0
var dataReceived: NSNumber?
func remoteRand() {
let dataToSend = 1
let myUrl = NSURL(string: "http://localhost/scripts/phpScript.php")
let request = NSMutableURLRequest(URL: myUrl!)
request.HTTPMethod = "POST"
let postString = "dataToSend =\(dataToSend)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
dispatch_async(dispatch_get_main_queue()) {
if (error != nil) {
self.displayAlertMessage((error?.localizedDescription)!)
return
}
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
if let parseJSON = json {
let dataReceived = parseJSON["dataValue"]
self.dataResult = (dataReceived as! NSNumber).integerValue
print("\(self.dataResult) is server response")
}
} catch { print(error)}
}
}
task.resume()
processResult()
}
func processResult() {
print(dataResult)
}
The result I get is:
0
1 is server response
How do I either make it wait for the response before proceeding to the next function or trigger the next function once completion is confirmed?
Thanks in advance!
The task completes on a different thread than which it is called, this is by design so network requests don't stop execution on the main thread. So your block of code is sent off async and processResult is called before the network request is finished. You can put the call in the do block or add a closure to the method that can be called.
func remoteRand(completion: (response: Int) ->()) {
// your code
// process JSON
// get value
completion(dataReceived)
// is passed back, just like the dataTaskWithRequest method to your caller where you can set the property on self, etc.
}
using it somewhere:
remoteRand { [weak self] (response) in
self?.dataResult = response
}
This question already has answers here:
How to make HTTP request in Swift?
(21 answers)
Closed 8 years ago.
I want a variable in php to get over in swift (or get the value for the variable). How can I do that?
$name = "William";
How can I get this string "William" to my Swift script? Can anyone help me?
I know it's something with JSON and POST or something but otherwise I am complete lost.
When you want to get data from PHP to an iOS device, I would recommend having the PHP code send it as JSON. JSON is easier for the the client app to parse (especially as your web service responses get more complicated) and it makes it easier to differentiate between a valid response and some generic server error).
To send JSON from PHP, I generally create an "associative array" (e.g., the $results variable below), and then call json_encode:
<?php
$name = "William";
$results = Array("name" => $name);
header("Content-Type: application/json");
echo json_encode($results);
?>
This (a) specifies a Content-Type header that specifies that the response is going to be application/json; and (b) then encodes $results.
The JSON delivered to the device will look like:
{"name":"William"}
Then you can write Swift code to call NSJSONSerialization to parse that response. For example, in Swift 3:
let url = URL(string: "http://example.com/test.php")!
let request = URLRequest(url: url)
// modify the request as necessary, if necessary
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print("request failed \(error)")
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: String], let name = json["name"] {
print("name = \(name)") // if everything is good, you'll see "William"
}
} catch let parseError {
print("parsing error: \(parseError)")
let responseString = String(data: data, encoding: .utf8)
print("raw response: \(responseString)")
}
}
task.resume()
Or in Swift 2:
let url = NSURL(string: "http://example.com/test.php")!
let request = NSMutableURLRequest(URL: url)
// modify the request as necessary, if necessary
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
guard let data = data else {
print("request failed \(error)")
return
}
do {
if let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String: String], let name = json["name"] {
print("name = \(name)") // if everything is good, you'll see "William"
}
} catch let parseError {
print("parsing error: \(parseError)")
let responseString = String(data: data, encoding: NSUTF8StringEncoding)
print("raw response: \(responseString)")
}
}
task.resume()
I'm answering this as an iOS/PHP dev rather than a Swift programmer.
You need to send an HTTP request to the webserver hosting the PHP script, which will return the contents of the web page given any specified parameters.
For example, if you sent an GET HTTP request to the following PHP script, the response would be "William" in the form of NSData or NSString depending on the method you use.
<?php
$name = "William";
echo $name;
?>
With a parameter GET http://myserver.com/some_script.php?name=William:
<?php
$name = $_GET['name']; // takes the ?name=William parameter from the URL
echo $name; // William
?>
As to the Swift side of things, there is a perfectly valid answer here which denotes one of the myriad methods of sending a request: https://stackoverflow.com/a/24016254/556479.