searchBar.resignFirstResponder() causing nil values - php

I am trying to create an iOS app using Swift and I need to implement a search feature using UISearchbar. It takes in a store name and searches for it in the database to return an array of store names. Below is the segment of the code which is giving me some errors. I followed this website closely http://swiftdeveloperblog.com/case-insensitive-search-with-swift-php-and-mysql/
func searchBarSearchButtonClicked(_ searchBar: UISearchBar)
{
if(searchBar.text!.isEmpty)
{
return
}
doSearch(searchWord: searchBar.text!)
}
func doSearch(searchWord: String){
mysearchBar.resignFirstResponder()
let myURL = NSURL(string: "http://localhost:8080/searchStore.php")
var request = URLRequest(url:myURL! as URL)
request.httpMethod = "POST"
let postString = "name=\(searchWord)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request, completionHandler:{ (data: Data?, response: URLResponse!, error: Error!) -> Void in
DispatchQueue.main.async() {
if error != nil{
self.displayAlertMessage(userMessage: error.localizedDescription)
return
}
do{
var _: Error?
//STOPPED HERE AS OF NOW
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
self.results.removeAll(keepingCapacity: false)
self.tableView.reloadData()
if let parseJSON = json{
if let stores = parseJSON["stores"] as? [AnyObject]{
for storeOjb in stores{
let name = (storeOjb["name"] as! String)
self.results.append(name)
}
self.tableView.reloadData()
}else if(parseJSON["message"] != nil){
let errorMessage = parseJSON["message"] as? String
if(errorMessage != nil){
self.displayAlertMessage(userMessage: errorMessage!)
}
}
}
} catch {
print(error)
}
}
})
task.resume()
}
I get 2 errors the first one is due to mysearchBar.resignFirstResponder(). The app terminates and I keep getting
"fatal error: unexpectedly found nil while unwrapping an Optional value"
The second error is when I remove mysearchBar.resignFirstResponder() I get
Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo=
{NSDebugDescription=No value.}
UPDATE:
I fixed the 2nd problem by entering this line
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
However, it seems that my postString variable is facing a problem
breakpoint check photo

You should set a breakpoint on the line that is giving you the error by clicking on the line number and run the program. Look for nil values by using the bottom left debugger pane window.
This will help you find what value is nil and if you already know what variable is nil please tell us!

Related

Cannot convert value of type '(NSData?, URLResponse?, NSError?) -> ()' to expected argument type '(Data?, URLResponse?

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.

Swift 3 function to POST data and I have an error when I receive JSon answer from my server

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.

Swift Error : Error Domain=NSCocoaErrorDomain Code=3840 " Problems with my Login Controller "

This is my code and I am unable to compile it .
I am trying to login to my server but it doesnt allow me so
Sorry I am new at programming and I've researched on stackoverflow, regarding this error , I can only parse Dictionary or Array. but I've googled by copying my JSON response but it doesnt work.
Any Suggestions would be helpful !!
import UIKit
class Login: UIViewController {
#IBOutlet var Username: UITextField!
#IBOutlet var Password: UITextField!
#IBAction func Login(sender: UIButton) {
let username=Username.text
let password=Password.text
let URL_LOGIN="http://172.22.95.116/SoilCondition/app/getLogin.php?USERNAME=" + username! + "&PASSWORD=" + password!;
let requestURL = NSURL(string: URL_LOGIN)
let request = NSMutableURLRequest(URL: requestURL!)
request.HTTPMethod = "POST"
let postParameters = "username="+username!+"&password="+password!;
request.HTTPBody = postParameters.dataUsingEncoding(NSUTF8StringEncoding)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request){
data, response, error in guard let data = data where error == nil
else {
print("error: \(error)")
return
}
do{
let myJSON = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
if let parseJSON = myJSON{
var msg: String!
msg = parseJSON["message"] as! String?
print(msg)
}
/* if let parseJSON = myJSON {
var msg : String!
msg = parseJSON["message"] as! String?
print(msg)
}*/
/*if data != nil {
json = NSString(data: data, encoding: NSUTF8StringEncoding) as! String
println("json: \(json)")
if let dictionary = parseJSON(jsonString) {
println("dictionary: \(dictionary)")
}*/
} catch let parseError{
print(parseError)
}
}
task.resume()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I found this question regarding error code 3840.
As it says there, the problem could be that your server doesn't return valid JSON to you.
Now, you say:
I can only parse Dictionary or Array
I don't know if that means that you are able to actually parse the response you receive from the server into valid JSON here:
let myJSON = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
But if it doesn't then a good place to start could be to verify whether your server actually returns valid JSON to you.
To do so, you could try calling your server directly from cURL or postman and see what you get in return.
Hope that helps you.

swift error: Code=3840 "Garbage at end."

I have this error
Error Domain=NSCocoaErrorDomain Code=3840 "Garbage at end." UserInfo={NSDebugDescription=Garbage at end.}
here is my swift code:
var exercise:String = ""
for value in numberOfExercisesArray{
exercise = exercise + value.text! + ","
}
if exercise.characters.last == ","{
exercise.removeAtIndex(exercise.endIndex.predecessor())
}
the string i want to post (exercise) is in the this context : "bench press,5,100"
However I cant get this string to go through because of the error above
Below is how i connect to my php/sql server:
let myURL = NSURL(string: "http://localhost:8888/saveWorkout.php");
let request = NSMutableURLRequest(URL:myURL!);
request.HTTPMethod = "POST";
let postString = "exercise=\(exercise)";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){
data, response, error in
if error != nil {
print("error=\(error)")
return
}
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as? NSDictionary
if let parseJSON = json{
let resultValue = parseJSON["status"] as! String!;
print("result: \(resultValue)")
if(resultValue == "Success"){
print("worked")
}
else{
print("not worked")
}
}
}
catch { print(error) }
}
task.resume();
How do I fix this error
Thanks
Your problem is , Your are using Json , and when you try to parse json actually you are not parsing it perfectly, Json can parse as Dictionary or Array , , check your json response try to decode it in any online json parser , to see how it's look like,
copy your server response (json)
search in google ( online json formatter )
past it there and see

Post request always wrapped by optional text

I have a very similar problem like in Why the http post request body always wrapped by Optional text in the Swift app
but I can´t apply the solution from this thread to my code, because I don´t have a request.setValue.
Does anyone know what I need to do to get rid of the Optional?
My Code:
#IBAction func LoginButtonTapped(sender: UIButton) {
let username = UsernameTextField.text
let password = PasswordTextField.text
if(username!.isEmpty || password!.isEmpty) {return; }
let request = NSMutableURLRequest (URL: NSURL(string: "http://myip/loginregister.php")!)
request.HTTPMethod = "POST"
let postString = "username=\(username)&password=\(password)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
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
}
let data = postString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
do {
if let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary {
let success = json["success"] as? Int // Okay, the `json` is here, let's get the value for 'success' out of it
print("Success: \(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()
You must unwrapping the value when get text from UITextField first, because the text property of UITextField allow nil
let username = UsernameTextField.text!
let password = PasswordTextField.text!
Explain more
When you unwrap the text of the UITextField, the username and password will be not nil variable.
The code compare empty should be:
if(username.isEmpty || password.isEmpty) {return }
If you does not unwrap, when you use this "\(username)", your are try to convert a nilable object to string, so the string result will be appended with a "Optional" text.
To Solve problem with Content-Type for request
Paste this line to your code. I don't believe that you do not have setValue method.
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type")

Categories