User Login & Register Problems - swift

Trying to set up Login and Register Controllers but I keep getting the same errors and all the solutions online have been no help. The Errors appear on lines: "displayMyAlertMessage" and UserDefaults.
#IBAction func signUpButton(_ sender: Any) {
let userName = userFirstName.text;
let userLast = userLastName.text;
if(userName!.isEmpty || userLast!.isEmpty)
{
displayMYAlertMessage("All Fields are RequireD");
return;
}
// Store data
UserDefaults.standardUserDefaults().setObject("userName", forKey: "userName")
UserDefaults.standardUserDefaults().setObject("userLast", forKey: "userLast")
let userName = UserDefaults.standardUserDefaults().stringForKey("userName")
let userLast = UserDefaults.standardUserDefaults().stringForKey("userLast")
// 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.dismiss(animated: true, completion:nil);
}
myAlert.addAction(okAction);
self.present(myAlert, animated:true, completion:nil);
}
}

Related

navigation controller doesn't work

Signup UIViewController design that validates email, password and confirm password.
Signup is embedded in NavigationController
func showAlert(ttl:String,msg:String){
let alert = UIAlertController(title: "\(ttl)", message: "\(msg)", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
#IBAction func signUp(_ sender: UIButton) {
if (email.text != nil && password.text != nil && confrimPassword.text != nil){
if !(isValidEmail(testStr: email.text!)){
showAlert(ttl: "Invaild Email-ID", msg: "Please enter an valid Email-ID")
}
else if !(isValidPassword(testStr: password.text)){
showAlert(ttl: "Invalid Password", msg: "Password must have at least one uppercase,one digit,one lowercase and minimum 8 characters")
}
else if !(passwordMatch(password: password.text!, confirmPassword: confrimPassword.text!)){
showAlert(ttl: "Passwords doesn't Match", msg: "Please re-enter your password")
}
else{
if Connectivity.isConnectedToInternet {
Authentication.Signup(for: email.text!, password: password.text!,finished: { resdata in do{ let res = try JSONSerialization.jsonObject(with: resdata) as! Dictionary<String, AnyObject>
print(res)
DispatchQueue.main.async {
let view: Verification = self.storyboard?.instantiateViewController(withIdentifier: "Verify") as! Verification
view.email = self.email.text!
//doesnot work
self.navigationController?.pushViewController(view, animated: true)
}
}
catch{
print("Error")
}
})
}
else{
showAlert(ttl: "No Internet", msg: "Please check your internet connection")
}
}
}
else{
self.showAlert(ttl: "Enter all Credentials", msg: " ")
}
}
}
Tried using segue also that doesn't suit my requirements
#IBAction func signUp(_ sender: UIButton) {
Authentication.Signup(for: email.text!, password: password.text!,finished: { resdata in do{
let res = try JSONSerialization.jsonObject(with: resdata) as! Dictionary<String, AnyObject>
print(res)
DispatchQueue.main.async {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "Verify") as! Verification
controller.email = self.email.text!
self.present(controller, animated: true, completion: nil)
}
}

PARSE user still active after log-out

I'm learning to use Parse Server to manage users and passwords. I have an app that lets the user log-in and store information in the server (age, weight, gender and name). But I'm having a problem, if the user logs out, the app takes them to the login page and, if after that they use a non-existing user or incorrect password, after showing the alert "Incorrect user or password", the app takes them to the main page with the previous user information. I'm not sure what is going on; the code I'm using to log in is this:
#IBAction func signInButton(_ sender: Any) {
let acl = PFACL()
acl.getPublicWriteAccess = true
PFUser().acl = acl
if userTextField.text == "" || passwordTextField.text == "" {
createAlert(title: "Error", message: "Both fields should be filled")
} else {
activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents() // UIApplication.shared() is now UIApplication.shared
PFUser.logInWithUsername(inBackground: userTextField.text!, password: passwordTextField.text!, block: { (user, error) in
self.activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents() // UIApplication.shared() is now UIApplication.shared
if error != nil {
var displayErrorMessage = "Please try again later."
let error = error as NSError?
if let errorMessage = error?.userInfo["error"] as? String {
displayErrorMessage = errorMessage
}
self.createAlert(title: "Login Error", message: displayErrorMessage)
} else {
print("Logged in")
let usuario = PFUser.current()
let dataUse = self.queryDownload(usuario: usuario!)
for items in dataUse {
let dataMeassure: GlucoseEvents = NSEntityDescription.insertNewObject(forEntityName: "GlucoseEvents", into: DatabaseController.getContext()) as! GlucoseEvents
dataMeassure.allAtributes = items
}
DatabaseController.saveContext()
self.performSegue(withIdentifier: "goToMain", sender: self)
}
})
}
}
Now, this problem only happens after the logout, so I'm guessing the error in that function. The code of the logout is:
#IBAction func logOut(_ sender: Any) {
let refreshAlert = UIAlertController(title: "Confirm", message: "Really LogOut?", preferredStyle: UIAlertControllerStyle.alert)
refreshAlert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action: UIAlertAction!) in
PFUser.logOutInBackground { (error) in
if error != nil {
self.createAlert(title: "Error", message: "Error")
}
}
self.performSegue(withIdentifier: "closedProf", sender: self)
}))
refreshAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action: UIAlertAction!) in
print("Handle Cancel Logic here")
}))
present(refreshAlert, animated: true, completion: nil)
}
Is there another way to logout and avoid this problem? Thanks
More info
So I tried to see if the problem was the server not returning a nil user. And added a print statement to the logout. Turns out that it's nil so I don't know why it is being stored (or where) but the LogOut returns a nil user.

How to store value and retrive it to use in next view controller after login using userdefaults?

I want to store the ngoid value in userDefaults so that I can access it in my next API call in the next viewController class. How do I do it?
Here is the code I have written:
#IBAction func loginbutton(_ sender: Any) {
let myUrl = NSURL(string: "http://www.shreetechnosolution.com/funded/ngo_login.php")
let request = NSMutableURLRequest(url:myUrl! as URL)
request.httpMethod = "POST"// Compose a query string
let postString = "uname=\(textfieldusername.text!)&password=\(textfieldpassword.text!)";
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest){ data , response , error in
if error != nil
{
//let alert = UIAlertView()
let alert = UIAlertController(title: "Alert Box !", message: "Login Failed", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
return
}
// You can print out response object
print("*****response = \(String(describing: response))")
let responseString = NSString(data: data! , encoding: String.Encoding.utf8.rawValue )
if ((responseString?.contains("")) == 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.present(alert, animated: true, completion: nil)
}
else {
print("correct good")
}
print("*****response data = \(responseString!)")
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary {
if let email = json["UserName"] as? String,
let password1 = json["passowrd"] as? String {
print ("Found User id: called \(email)")
}
let msg = (json.value(forKey: "message") as! NSString!) as String
//let id = json.value(forKey: "NgoId") as! Int!
let ngoid = json.value(forKey: "NgoId") as? String
print(ngoid ?? "")
let defaults = UserDefaults.standard
defaults.set(ngoid, forKey: "ngoid")
print(ngoid!)
DispatchQueue.main.async {
self.alert = UIAlertController(title: "Alert Box!", message: "\(msg)", preferredStyle: .alert)
self.action = UIAlertAction(title: "OK", style: .default) { (action) -> Void in
let vtabbar1 = self.storyboard?.instantiateViewController(withIdentifier: "tabbar1")
self.navigationController?.pushViewController(vtabbar1!, animated: true)
}
self.alert.addAction(self.action)
self.present(self.alert, animated: true, completion: nil)
}
}
}
catch let error {
print(error)
}
}
task.resume()
}
You could use UserDefaults but if you only need to use the value on the next viewController you should use a segue for this purpose. Here is a guide of how that works. Otherwise use UserDefaults like the example below:
// To set the value
UserDefaults.standard.set(ngoid, forKey: "NgoId")
// To get the value
let id = UserDefaults.standard.string(forKey: "NgoId")
This is not a best way to save in user default and then use in next ViewController, use this overdid method
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowCounterSegue"
{
if let destinationVC = segue.destinationViewController as? OtherViewController {
destinationVC.ngoid = ngoid
}
}
}
use ngoid anywhere in your next ViewController api call.

iOS swift 3.0 Json parsing and alert issue

I'm working on login form. I'm a fresher on iOS development.
After successful login, I want to show an alert after completion of json parsing. I've parsed Ngoid inside a do while block. Now I want to pass the value "Ngoid" to the next view controller so that it can be used to fetch the further data.
Main Problem: Here is the code I have written and it gives me error to write alert it on main thread only.
As I want the "Ngoid" value for further use there, so how should I write it and what is the correct way to execute the code?
Here is the code I have written:
#IBAction func loginbutton(_ sender: Any) {
let myUrl = NSURL(string: "http://www.shreetechnosolution.com/funded/ngo_login.php")
let request = NSMutableURLRequest(url:myUrl! as URL)
request.httpMethod = "POST"// Compose a query string
let postString = "uname=\(textfieldusername.text!)&password=\(textfieldpassword.text!)";
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest){ data , response , error in
if error != nil
{
//let alert = UIAlertView()
let alert = UIAlertController(title: "Alert Box !", message: "Login Failed", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
return
}
// You can print out response object
print("*****response = \(String(describing: response))")
let responseString = NSString(data: data! , encoding: String.Encoding.utf8.rawValue )
if ((responseString?.contains("")) == 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.present(alert, animated: true, completion: nil)
}
else {
print("correct good")
}
print("*****response data = \(responseString!)")
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary {
if let email = json["UserName"] as? String,
let password1 = json["passowrd"] as? String {
print ("Found User id: called \(email)")
}
let msg = (json.value(forKey: "message") as! NSString!) as String
let id = (json.value(forKey: "NgoId") as! NSString!) as String
// let alert : UIAlertView = UIAlertView(title: "Alert box!", message: "\(msg!).",delegate: nil, cancelButtonTitle: "OK")
// alert.show()
self.alert = UIAlertController(title: "Alert Box!", message: "\(msg)", preferredStyle: .alert)
print("the alert\(self.alert)")
self.action = UIAlertAction(title: "OK", style: .default) { (action) -> Void in
let viewControllerYouWantToPresent = self.storyboard?.instantiateViewController(withIdentifier: "pass1") as! ViewControllerngodetails
viewControllerYouWantToPresent.temp1 = self.id
self.present(viewControllerYouWantToPresent, animated: true, completion: nil)
}
self.alert.addAction(self.action)
self.present(self.alert, animated: true, completion: nil)
}
}catch let error {
print(error)
}
}
task.resume()
}
A pro tip:
All your UI related tasks need to be done in the main thread. Here you are presenting the alert inside a closure which executes in a background thread, thats the problem. You need to call the main queue and present alert in that block.
EDIT:
Just put your alert code in this-
For Swift 3-
Get main queue asynchronously
DispatchQueue.main.async {
//Code Here
}
Get main queue synchronously
DispatchQueue.main.sync {
//Code Here
}
Every UI update has to be on main thread:
#IBAction func loginbutton(_ sender: Any) {
let myUrl = NSURL(string: "http://www.shreetechnosolution.com/funded/ngo_login.php")
let request = NSMutableURLRequest(url:myUrl! as URL)
request.httpMethod = "POST"// Compose a query string
let postString = "uname=\(textfieldusername.text!)&password=\(textfieldpassword.text!)";
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest){ data , response , error in
if error != nil
{
DispatchQueue.main.async {
let alert = UIAlertController(title: "Alert Box !", message: "Login Failed", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
// Present Alert Controller
self.present(alert, animated: true, completion: nil)
}
return
}
// You can print out response object
print("*****response = \(String(describing: response))")
let responseString = NSString(data: data! , encoding: String.Encoding.utf8.rawValue )
if ((responseString?.contains("")) == nil) {
print("incorrect - try again")
DispatchQueue.main.async {
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.present(alert, animated: true, completion: nil)
}
}
else {
print("correct good")
}
print("*****response data = \(responseString!)"
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary {
if let email = json["UserName"] as? String,
let password1 = json["passowrd"] as? String {
print ("Found User id: called \(email)")
}
let msg = (json.value(forKey: "message") as! NSString!) as String
let id = (json.value(forKey: "NgoId") as! NSString!) as String
DispatchQueue.main.async {
self.alert = UIAlertController(title: "Alert Box!", message: "\(msg)", preferredStyle: .alert)
print("the alert\(self.alert)")
self.action = UIAlertAction(title: "OK", style: .default) { (action) -> Void in
let viewControllerYouWantToPresent = self.storyboard?.instantiateViewController(withIdentifier: "pass1") as! ViewControllerngodetails
viewControllerYouWantToPresent.temp1 = self.id
self.present(viewControllerYouWantToPresent, animated: true, completion: nil)
}
self.alert.addAction(self.action)
self.present(self.alert, animated: true, completion: nil)
}
}
}catch let error {
print(error)
}
}
task.resume()
}

UIAlertView in closures callback function in Swift

I need to login through api when user click login button. The return results might failure or success. I want to use alterview to notice the user.
I defined one global variable in class:
var responseString:String = "";
In button click event:
#IBAction func login(sender: AnyObject) {
sendPostLoginRequest {
results in
println("here:\(results)")
self.responseString = results
}
var myAlert = UIAlertController(title:"Alert", message:self.responseString, preferredStyle: UIAlertControllerStyle.Alert);
let okAction = UIAlertAction(title:"Ok", style:UIAlertActionStyle.Default, handler:nil);
myAlert.addAction(okAction);
self.presentViewController(myAlert, animated:true, completion:nil);
}
The self.responseString is empty, even through i can get it in sendPostLoginRequest function:
func sendPostLoginRequest(completionHandler:(result:String)->()){
let name = usernamefield.text
let password = passwordfield.text
let request = NSMutableURLRequest(URL: NSURL(string: "http://www.xxx.xxx/api/user/login")!)
request.HTTPMethod = "POST"
let postString = "username=\(name)&password=\(password)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
}
let json = JSON(data: data)
println("results: \(json) ")
self.responseString = json[0].string!
//json[0].string! can be success or failure
completionHandler(result:self.responseString)
}
task.resume()
}
The way I see it, I think when you click the button, the alertView is shown without the responseString or nil. The problem is you are anticipating the block will get called later on and hence the data for responseString will be set later in time but the code below will continue to execute.
The long way to do is:
//observe this variable and when something changes we will alert it
var responseString:String {
didSet{
//do some checking or other work
presentAlert(responseString)
}
}
#IBAction func login(sender: AnyObject) {
sendPostLoginRequest {
results in
println("here:\(results)")
self.responseString = results
}
}
func presentAlert(msg:String){
var myAlert = UIAlertController(title:"Alert", message:msg, preferredStyle: UIAlertControllerStyle.Alert);
let okAction = UIAlertAction(title:"Ok", style:UIAlertActionStyle.Default, handler:nil);
myAlert.addAction(okAction);
self.presentViewController(myAlert, animated:true, completion:nil);
}
The short way to do is:
#IBAction func login(sender: AnyObject) {
sendPostLoginRequest {
results in
println("here:\(results)")
self.responseString = results
dispatch_async(dispatch_get_main_queue(), { () -> Void in
//update ui from main thread always
self.presentAlert(results) //may pass responseString too
})
}
}
func presentAlert(msg:String){
var myAlert = UIAlertController(title:"Alert", message:msg, preferredStyle: UIAlertControllerStyle.Alert);
let okAction = UIAlertAction(title:"Ok", style:UIAlertActionStyle.Default, handler:nil);
myAlert.addAction(okAction);
self.presentViewController(myAlert, animated:true, completion:nil);
}
Had you put the code below the closure inside it would have worked but you would be running UI things from other threads which are bad so use Dispatch Async to work for long-running operations on a separate thread.
Let me know if that helps and hope it does. Cheers!