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){}
}
}...
Related
This is my swift code for registration page.
let headers : HTTPHeaders = ["Content-Type": "application/json"]
let postString : Parameters = ["name": "com", "email": "raj123#v", "mobile": "123", "password": "123"]
let signUpUrl = "myURL/api_register.php"
Alamofire.request(signUpUrl, method: .post, parameters: postString, encoding: JSONEncoding.default, headers: headers).responseJSON {
response in
switch response.result {
case .success:
print(response)
case .failure(let eror):
print(eror)
}
this is my php api code :
header('Content-Type: application/json');
$return_arr = array();
$username=mysqli_real_escape_string($link,$_POST["name"]);
$email=mysqli_real_escape_string($link,$_POST["email"]);
$mobile=mysqli_real_escape_string($link,$_POST["mobile"]);
$password=mysqli_real_escape_string($link,$_POST["password"]);
$result=mysqli_query($link,"insert into users(name,email,mob,password) values('$username','$email','$mobile','$password')");
if(mysqli_num_rows($result))
{
$row_array['status']=true;
array_push($return_arr,$row_array);
}
else
{
$row_array['status']=false;
array_push($return_arr,$row_array);
}
echo json_encode($return_arr);
mysqli_close($link);
Nil entry is inserting into a database with alamofire. where is the actual problem, I test all but can't get.
if I don't use Alamofire and This code is not working also:
let signUpUrl = URL(string: "myURL/api_register.php")
var request = URLRequest(url: signUpUrl!)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let postString : Parameters = ["name": "com", "email": "raj123#v", "mobile": "123", "password": "123"]
print("\(postString)")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: postString, options: .prettyPrinted)
//print(request.description)
} catch let error {
print(error.localizedDescription)
displayMessage(userMessage: "Something went wrong")
return
}
Regarding second approach you can use something like this
let newUrl = NSURL(string:"https://.......")
let urlRequest = NSMutableURLRequest(url: newUrl! as URL, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 60.0)
urlRequest.httpMethod = "POST"
let body = String(format:"name=%#&email=%#","picko","werr#yahoo").data(
using: String.Encoding.utf8,allowLossyConversion: false)
urlRequest.httpBody = body
let queue = OperationQueue()
NSURLConnection.sendAsynchronousRequest(urlRequest as URLRequest, queue: queue)
{
(response: URLResponse?,data: Data?, error: Error?) in
/* Now we may have access to the data, but check if an error came back first or not */
if error == nil
{
do {
let responseDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:Any]
print("responseDict:\(responseDict)")
} catch let caught as NSError
{
print("Error in json \(caught)")
}
}
else if data?.count == 0 && error == nil
{
print("Nothing was downloaded")
}
else if error != nil
{
print("Error happened = \(String(describing: error))")
}
}
I have this function working fine (feel free if you have a fine tuning !) :
func httpPostRequest(urlString: String, dataToPost: Dictionary<String, String>) {
let url = URL(string: urlString)!
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "POST"
do {
request.httpBody = try JSONSerialization.data(withJSONObject: dataToPost, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {
print("error=\(error) AND error = nil !")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // Check for http(s) errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
return
}
guard let data = data, error == nil else { // Check for fundamental networking error
print("error=\(error)")
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print("JSON = ")
print(json)
}
} catch let error {
print(error.localizedDescription)
return
}
})
task.resume()
}
The PHP server return this JSon string :
{'exception': false, 'success': false, 'status': -8, 'message': 'Your email address is not valid !', 'confirmMessage': 'null', 'html': 'null', 'data': 'null'}
This is what is diplay in the XCode Console :
JSON =
["status": -8, "data": null, "html": null, "message": Your email address is not valid !, "exception": 0, "confirmMessage": null, "success": 0]
I need to return this JSon string to continue with this data.
How can I convert my function for do this ?
This should be the function.
func httpPostRequest(urlString: String, dataToPost: Dictionary<String, String>, completionHandler:#escaping (Dictionary<String, Any>) -> ()) {
let url = URL(string: urlString)!
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "POST"
do {
request.httpBody = try JSONSerialization.data(withJSONObject: dataToPost, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {
print("error=\(error) AND error = nil !")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // Check for http(s) errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
return
}
guard let data = data, error == nil else { // Check for fundamental networking error
print("error=\(error)")
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print("JSON = ")
print(json)
completionHandler(json)
}
} catch let error {
print(error.localizedDescription)
return
}
})
task.resume()
}
I have a function in Swift 3 to POST data to a PHP server. The PHP server send a JSon answer to iOS and I have an error.
This is my function :
func sendRequestPost(urlString: String, dataToPost: String, completion: #escaping (_ dictionary: NSDictionary?, _ error: Error?) -> Void) {
DispatchQueue.global(qos: .background).async {
var request = URLRequest(url: URL(string: urlString)!)
let postString = dataToPost
request.httpMethod = "POST"
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=\(error)")
completion(nil, error)
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // Check for http(s) errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
// make error here and then
completion(nil, error)
return
}
let responseString = String(data: data, encoding: .utf8)
print("responseString : \(responseString)!")
DispatchQueue.main.async {
print("DispatchQueue.main.async")
do {
print("enter do")
let jsonDictionary:NSDictionary = try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] as NSDictionary
print("jsonDictionary")
print(jsonDictionary)
completion(jsonDictionary, nil)
} catch {
print("CATCH ERROR !")
completion(nil, error)
}
}
}
task.resume()
}
}
For example I call my function like that :
let url = "https://mywebsite.com/signup/ios/signup.php"
let postData = "username=\(txtUsername.text!)&password=\(txtPassword.text!)&confirmPassword=\(txtConfirmPassword.text!)&email=\(txtEmail.text!)&firstname=\(txtFirstname.text!)&lastname=\(txtLastname.text!)"
sendRequestPost(urlString: url, dataToPost: postData) {
dictionary, error in
print("---directory---")
print(dictionary)
print("---error---")
print(error)
print("==========")
This is what I see in the console :
responseString : "{\"exception\":false,\"success\":false,\"status\":-9,\"message\":\"This username already exist !\",\"confirmMessage\":\"null\",\"html\":\"null\",\"data\":\"boblongueuil\"}"!
DispatchQueue.main.async
---ENTER DO :
CATCH ERROR !
---directory---
nil
---error---
Optional(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.})
So how can I return the JSon string after call this function to see a registration is OK or registration have a problem (in this case the username already exist in database). I change answer from my PHP server to an array.
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 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)")
}
//...