I get the following error when i try to get data. In the internet i read that its because the php script is invalid and don't return json data. But the php script runs fine and outputs the right data.
Error Message :
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.}
I tried to allow fragments but then i get just another error message.
Here is the swift code where i try to get the data :
let myUrl = NSURL(string: "http://xxxxxxxxxxx.xxx/xxxxxxxx.php")
let request = NSMutableURLRequest(URL: myUrl!)
request.HTTPMethod = "POST"
let postString = "userEmail=\(userEmail!)&userPassword=\(userPassword!)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
dispatch_async(dispatch_get_main_queue())
{
if(error != nil)
{
var alert = UIAlertController(title: "Achtung", message: error?.localizedDescription, preferredStyle: UIAlertControllerStyle.Alert)
let action = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
}
print("1")
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
if let parseJSON = json {
let userId = parseJSON["userId"] as? String
if( userId != nil)
{
print("SUCESS FUCKER")
let mainView = self.storyboard?.instantiateViewControllerWithIdentifier("main") as! FlickrPhotosViewController
let mainPageNavi = UINavigationController(rootViewController: mainView)
//open mainView
let appdele = UIApplication.sharedApplication().delegate
appdele?.window??.rootViewController = mainPageNavi
} else {
let userMassage = parseJSON["message"] as? String
let myAlert = UIAlertController(title: "Alert", message: userMassage, preferredStyle: UIAlertControllerStyle.Alert);
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)
myAlert.addAction(okAction);
self.presentViewController(myAlert, animated: true, completion: nil)
}
}
} catch{
print(error)
print("FAILED CATCHED")
}
}
}).resume()
and this is the important part of the php file :
$userSecuredPassword = $userDetails["user_password"];
$userSalt = $userDetails["salt"];
if($userSecuredPassword === sha1($userPassword . $userSalt))
{
$returnValue["status"]="200";
$returnValue["userFirstName"] = $userDetails["first_name"];
$returnValue["userLastName"] = $userDetails["last_name"];
$returnValue["userEmail"] = $userDetails["email"];
$returnValue["userId"] = $userDetails["user_id"];
} else {
$returnValue["status"]="403";
$returnValue["message"]="User not found";
echo "failed";
echo json_encode($returnValue);
return;
}
echo json_encode($returnValue);
$returnValue returns this when i print it:
Array ( [status] => 200 [userFirstName] => Paul [userLastName] => Heinemeyer [userEmail] => paul_heine [userId] => 63 )
When you properly format your PHP code, you will see, that in the else part you have
echo "failed";
echo json_encode($returnValue);
which results in
failed{...}
As the error message already says, this "JSON text did not start with array or object ..."
Maybe there is similar output for the other if part.
Related
I am new to Swift and I am trying to create secure login with PHP in backend. But somewhere I am going wrong, my viewcontroller is segue to next view controller even though i Don't give login credential and getting following error in console:
Please help !!
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
my code:
#IBAction func loginAuthentication(sender: UIButton) {
//declare parameter as a dictionary which contains string as key and value combination. considering inputs are valid
let myUrl = NSURL(string: "my url");
var request = NSMutableURLRequest(URL:myUrl!)
request.HTTPMethod = "POST"// Compose a query string
let postString = "username = \( NameTextField.text!) & password = \( passwortTextField.text!) ";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data , response , error in
if error != nil
{
let alert = UIAlertView()
alert.title = "Login Failed!"
alert.message = "Error: \(error)"
alert.delegate = self
alert.addButtonWithTitle("OK")
alert.show()
return
}
// You can print out response object
print("*****response = \(response)")
let responseString = NSString(data: data! , encoding: NSUTF8StringEncoding )
if ((responseString?.containsString("")) != nil) {
print("incorrect - try again")
let alert = UIAlertController(title: "Try Again", message: "Username or Password Incorrect", preferredStyle: .Alert)
let yesAction = UIAlertAction(title: "Nochmalversuchen", style: .Default) { (action) -> Void in
}
// Add Actions
alert.addAction(yesAction)
// Present Alert Controller
self.presentViewController(alert, animated: true, completion: nil)
}
else {
print("correct good")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("toPflegerProfile")
self.presentViewController(controller, animated: true, completion: nil)
}
print("*****response data = \(responseString)")
do {
//create json object from data
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? [String: Any] {
if let email = json["UserName"] as? String,
let password = json["passowrd"] as? String {
print ("Found User id: called \(email)")
}
}
} catch let error {
print(error)
}
}
task.resume()
}
php code :
<?php
require_once 'db.php';
$conn = connect();
if($conn)
{
if (isset($_GET['loginuser']))
{
//Getting post values
require_once 'getuserdata.php';
//1.Check if user is looged in
$loggedin = checkuserloggedin($username, $conn);
if ($loggedin)
{
$response['error']=true;
$response['message']='User is already logged in!';
}
else
{
//2.If not, insert pfleger
//Inserting log in values
if (insertuserdata($name,$username, $password, $gps, $logintime, $conn))
{
$response['error']=false;
$response['message']='Log Data added successfully';
}
else
{
$response['error']=true;
$response['message']='Could not add log in data';
}
}
}
else
{
$response['error']=true;
$response['message']='You are not authorized';
}
echo json_encode($response);
?>
use this
var request = URLRequest(url: URL(string: “url”)!)
request.httpMethod = "POST"
let userName = self.emailTextField.text!
let password = self.passtextField.text!
let postString = NSString(format: "emailId=%#&password=%action=%#",userName, password,”action name”)
request.httpBody = postString.data(using: String.Encoding.utf8.rawValue)
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=\(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 = \(response)")
}
do {
let jsonResults : NSDictionary = try JSONSerialization.jsonObject(with: data, options: [])as! NSDictionary
print("login json is ---%#",jsonResults)
let str = jsonResults.object(forKey: "status")as! String
if (str == "Success")
{
let newdic:NSDictionary = jsonResults.object(forKey: "response") as! NSDictionary
} catch {
// failure
print("Fetch failed: \((error as NSError).localizedDescription)")
}
}
task.resume()
Hello I'm writing an ios swift 3 application to communicate with a website, the app after doing a number of things should return a type value of false or true, but it does not happen you can tell me where I'm wrong and how to correct the mistake!
VALUE RETURN at swift:
....response = Optional( { URL: "http://....myurl.php"}.....
SWIFT CODE:
let myUrl = URL(string: "http://....myurl.php");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"// Compose a query string
let postString = "username=James&password=Bond";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil
{
print("error=\(error)");
// return false
}
print("response = \(response)")
}
task.resume()
return 0;
PHP CODE:
include 'user.php';
$user = new User();
$username= $_REQUEST["username"];
$password = $_REQUEST["password"];
if($user->login($username,$password)==true){
echo json_encode("true");
}
else{
echo json_encode("false");
}
ERROR IMAGE:
You need to look into data and not response.
And maybe you should encapsulate your return value in your PHP code, like this for example:
if($user->login($username,$password)==true){
echo '{"success":true}';
}else{
echo '{"success":false}';
}
And then get the result in swift:
func login(request_completed:#escaping (_ succeded:Bool) -> ()) {
let myUrl=URL(string: "http://....myurl.php");
var request=URLRequest(url:myUrl!)
request.httpMethod="POST"
let postString = "username=James&password=Bond";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task=URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
guard data != nil else {
print("no data found")
request_completed(false)
return
}
do{
if let jsonData=try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary{
print(jsonData)
let success=jsonData.value(forKey: "success") as! Bool
if success{
print("login succeded")
request_completed(true)
return
}else{
print("login failed")
request_completed(false)
return
}
}else{
print("could not parse json")
request_completed(false)
}
}catch{
print("request failed")
request_completed(false)
}
})
task.resume()
}
So basically I have a login script on my server that returns a result depending on if the user credentials are correct or wrong, and I have an iOS App that sends data to that login script to return the correct or wrong result.
Here is the relevant part of my login page that shows the return code ($userDetails being the TRUE or FALSE check of correct or wrong credentials) :
$userDetails = $dao->getUserDetailsWithHashedPassword($email,$password);
if($userDetails===TRUE) {
$returnValue["status"] = "Success";
$returnValue["message"] = "User logged in !";
echo json_encode($returnValue);
} else {
$returnValue["status"] = "error";
$returnValue["message"] = "User not found";
echo json_encode($returnValue);
}
If anyone needs to see what that getUserDetailsWithHashedPassword() does, click here
Using Postman to test the HTTP POST, everything works fine, I get the correct result when posting email#email.com & testpassword in the body and using the correct Content-Type (application/x-www-form-urlencoded) :
{"status":"error","message":"User not found"}
Now my iOS is supposed to interpret this with this code :
#IBAction func loginButtonPressed(_ sender: AnyObject) {
let userEmail = emailLoginField.text
let userPassword = passwordLoginField.text
// Check for empty fields
if((userEmail?.isEmpty)! || (userPassword?.isEmpty)!) {
// Display alert message
displayMyAlertMessage(userMessage: "All fields are required");
return ;
}
// Send user data to server side
let myUrl = URL(string: "https://support.vincentsolutions.ca/userLogin.php");
var request = URLRequest(url:myUrl!);
request.httpMethod = "POST";
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let postString = "email=\(userEmail!)&password=\(userPassword!)";
request.httpBody = postString.data(using: String.Encoding.utf8);
URLSession.shared.dataTask(with: request, completionHandler: { (data:Data?, response:URLResponse?, error:Error?) -> Void in
if error != nil {
print ("error=\(error)")
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
var resultValue = parseJSON["status"] as? String
print("result: \(resultValue)")
var isUserLoggedIn:Bool = false;
if(resultValue=="Success") {
// Login is successful
UserDefaults.standard.set(true, forKey: "isUserLoggedIn");
UserDefaults.standard.synchronize();
self.performSegue(withIdentifier: "loginSuccesful", sender: self)
}
var messageToDisplay:String = parseJSON["message"] as! String!;
if(!isUserLoggedIn) {
messageToDisplay = parseJSON["message"] as! String!;
}
DispatchQueue.main.async(execute: {
// Display alert message with confirmation.
var myAlert = UIAlertController(title: "Alert", message: messageToDisplay, preferredStyle: UIAlertControllerStyle.alert);
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default){ action in
self.dismiss(animated: true, completion: nil);
}
myAlert.addAction(okAction);
self.present(myAlert, animated: true, completion: nil);
});
}
} catch let error as NSError {
print("An error occured: \(error)")
}
}).resume()
Now I'm getting this error when I run the code from the iOS App :
An error occured: Error Domain=NSCocoaErrorDomain Code=3840 "JSON text
did not start with array or object and option to allow fragments not
set."
Does anyone see what could be wrong here ? I've tried looking for that error here on SO and on the internet but couldn't find anything related to my situation.
That is because the response you are receiving from the URL probably not in correct JSON format. I will suggest you to do 2 things -
Try to NSLog the data and response
Try this
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! NSDictionary
I would like to display a UIAlertController after getting a jSON response from my php server, so upon checking there is a return id from the response, in the if else statement, i wrote a code to display a UIAlertController but i could not get it to work.
Here is a snippet of my error
Assertion failure in -[UIKeyboardTaskQueue waitUntilAllTasksAreFinished]
My IBAction button codes
#IBAction func btnRegister(sender: AnyObject) {
let parameters = ["name": tfName.text! , "contact": tfContact.text! ,"email": tfEmail.text!] as Dictionary<String, String>
let request = NSMutableURLRequest(URL: NSURL(string:"http://192.168.1.8/safeproject/registerprofile.php")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
//Note : Add the corresponding "Content-Type" and "Accept" header. In this example I had used the application/json.
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(parameters, options: [])
let task = session.dataTaskWithRequest(request) { data, response, error in
guard data != nil else {
print("no data found: \(error)")
return
}
let successAlert = UIAlertController(title: "Registration Status", message:"Register Success", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default) { _ in })
let failAlert = UIAlertController(title: "Registration Status", message:"Register Fail", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default) { _ in })
// Present the controller
do {
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
print("Response: \(json)")
let id = json["id"]!
if(id.isEqual(""))
{
self.presentViewController(failAlert, animated: true){}
print("User register fail");
}
else
{
self.presentViewController(successAlert, animated: true){}
print("User register success");
}
} else {
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)// No error thrown, but not NSDictionary
print("Error could not parse JSON: \(jsonStr)")
}
} catch let parseError {
print(parseError)// Log the error thrown by `JSONObjectWithData`
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: '\(jsonStr)'")
}
}
task.resume()
}
When you are trying to display the alert controller you are working on a separate thread so you need to switch back before displaying it.
if(id.isEqual("")){
NSOperationQueue.mainQueue().addOperationWithBlock {
self.presentViewController(failAlert, animated: true){}
}
}...
I recieve an error as desciribed in the title.
Invalid conversion from throwing function of type '(_, _, _) throws -> ()' to non-throwing function type '(NSData?, NSURLResponse?, NSError?) -> Void'
after the session dataTaskWithRequest. It's a simple user register to PHP and mysql. In Swift xcode 7.3.
func displaymyalertmessage(userMessage:String)
{
var myAlert = UIAlertController(title: "Alert" , message:userMessage, preferredStyle: UIAlertControllerStyle.Alert);
let OkAction = UIAlertAction (title: "Ok", style: UIAlertActionStyle.Default, handler:nil);
myAlert.addAction(OkAction);
self.presentViewController(myAlert, animated:true, completion:nil);
}
// check for empty fields
if(useremail!.isEmpty || username!.isEmpty ||
userpassword!.isEmpty ||
userrepeatpassword!.isEmpty){
// Display alert message
displaymyalertmessage("All fields are required");
return;
}
//Check if passwords match
if(userpassword != userrepeatpassword)
{
// display an alert message
displaymyalertmessage("Passwords do not match");
return;
}
// send data to server
let myUrl = NSURL(string: "http://example/xxx.php")
let request = NSMutableURLRequest(URL:myUrl!);
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST";
let postString = "email=\(useremail)&password=\(userpassword)&username=\(username)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
it's on the next task i recieve error (_, _, _)
do {
let task = session.dataTaskWithRequest(request)
{ (data, response, error) in
// if error
if error != nil {
print("error=\(error)")
return
}
var err: NSError?
var json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers, error: &err) as? NSDictionary
if let parseJSON = json {
var resultvalue = parseJSON["status"] as? String
printld("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!;
}
dispatch_async(dispatch_get_main_queue(), {
// Display alert message with confirmation
var myAlert = UIAlertController(title: "Alert" , message: "Registration is successful. Thank You", preferredStyle: UIAlertControllerStyle.Alert);
let OkAction = UIAlertAction (title: "Ok", style: UIAlertActionStyle.Default){ ACTION in
self.dismissViewControllerAnimated(true, completion: nil);
}
myAlert.addAction(OkAction);
self.presentViewController(myAlert, animated:true, completion:nil)
});
} }
task.resume()
}
I have tried many things but i am stuck unable to clear this error.
You need to move try-catch into the callback block scope. Also you should not pass err by reference into JSONObjectWithData as it throws an error. This should work:
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)")
}
//...