Logic errors with password authentication code - ios

My code is as follows:
#IBAction func clicked(_ sender: Any) {
let ref = Database.database().reference()
let pass = password.text
var firpass = ""
var bool = false;
ref.child(name.text as! String).child("password").observeSingleEvent(of: .value, with: { dataSnapshot in
firpass = dataSnapshot.value as? String ?? ""
if firpass == pass {
bool = true
}
if bool {
self.sendname = self.name.text!
let vc = DatabaseTableViewController(nibName: "DatabaseTableViewController", bundle: nil)
vc.finalName = self.sendname
self.navigationController?.pushViewController(vc, animated: true)
self.performSegue(withIdentifier: "username", sender: self)
} else {
let alert = UIAlertController(title: "Error", message: "Incorrect username or password", preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
self.performSegue(withIdentifier: "failed", sender: self)
}
})
}
override func shouldPerformSegue(withIdentifier identifier: String?, sender: Any?) -> Bool {
if let ident = identifier {
if ident == "failed" {
return false
}
}
return true
}
When I give the right username and password, I go to the next page, but I get this error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<OCRApp.ViewController: 0x105e00f60>) has no segue with identifier 'failed''
*** First throw call stack:
(0x1877aaa48 0x1874d1fa4 0x18b206010 0x104a5b58c 0x104a5ba20 0x104aaa19c 0x104aaa598 0x104a8bb40 0x105cd97fc 0x105cdabd8 0x105ce8c34 0x1877285e4 0x1877235d8 0x187722adc 0x1916a8328 0x18b81dae0 0x104a6cdb0 0x1875ac360)
libc++abi.dylib: terminating with uncaught exception of type NSException
When I give the wrong username/password, I still went to the next page, and I got the above error but with identifier failed instead; when I took out the line self.performSegue(withIdentifier: "failed", sender: self), I still went to the next page and got the message:
Warning: Attempt to present <UIAlertController: 0x102978a00> on <OCRApp.ViewController: 0x10170a650> which is already presenting <OCRApp.DatabaseTableViewController: 0x10206beb0>
What I want is to progress to the next page without errors if you put the correct authentication, and to get just the alert and stay on current page if you give incorrect authentication. How do I do this?

Either use push or performSegue, you cant use both at same time. that will push your view controller twice. I have updated the code below.
#IBAction func clicked(_ sender: Any) {
let ref = Database.database().reference()
let pass = password.text
var firpass = ""
var bool = false;
ref.child(name.text as! String).child("password").observeSingleEvent(of: .value, with: { dataSnapshot in
firpass = dataSnapshot.value as? String ?? ""
if firpass == pass {
bool = true
}
if bool {
self.sendname = self.name.text!
let vc = DatabaseTableViewController(nibName: "DatabaseTableViewController", bundle: nil)
vc.finalName = self.sendname
self.navigationController?.pushViewController(vc, animated: true) // either use push or performSegue, you cant use both.
// self.performSegue(withIdentifier: "username", sender: self)
} else {
let alert = UIAlertController(title: "Error", message: "Incorrect username or password", preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil) // if there is an error, you do not need to performSegue.
// self.performSegue(withIdentifier: "failed", sender: self)
}
})
}

We do not have information about your segues, I suggest you instantiate your next ViewController. You can use something like this:
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NextViewController") as? NextViewController
present(vc, animated: true, completion: nil)

Related

How can I show a popup in a ViewController

I want to show this popup in my view controller and when I push the button go back
This is the part of I want to show the pop up:
#IBAction func entrarAction(_ sender: UIButton) {
sender.isEnabled = false
let l = showLoader()
let user = userTextField.text!
let passwd = passwordTextField.text!
if !validaEntrada(user: user, password: passwd){
// TODO: show errors!
// Show popup here
return
}
let login = VenLogin(usuario: user, contrasenia: passwd)
try! RequestManager.fcReq(url: .login, req: login, res: VenLoginResponse.self) { loginResp, err in
sender.isEnabled = true
l.dismiss(animated: true, completion: {
if let r:VenLoginResponse = loginResp as? VenLoginResponse {
if r.code0 {
let c = self.getAppDelegateContainer()
c.register(from: .loginResponse, value: r)
c.register(from: .tokenJwt, value: r.tokenJwt!)
self.pushServicios()
}
}
})
}
}
Instead of a custom View Controller for your popup you can use an Alert View
#IBAction func entrarAction(_ sender: UIButton) {
sender.isEnabled = false
let l = showLoader()
let user = userTextField.text!
let passwd = passwordTextField.text!
if !validaEntrada(user: user, password: passwd){
// Show popup here
showErrorAlert()
return
// the rest of your code
}
func showErrorAlert() {
let alert = UIAlertController(title: "Usuario o contraseña no válido", message: "", preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Aceptar", style: UIAlertAction.Style.cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
But if you still want to use your custom View Controller use this to show the popup:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let popupErrorLogin = storyboard.instantiateViewController(withIdentifier: "PopupErrorLogin") as! PopupErrorLogin
self.present(popupErrorLogin, animated: true, completion: nil)
And this to close it:
#IBAction func aceptarAction(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}

Swift 5 - Navigation Pages

I am just getting to work with Swift 5 and have to update my apps. I use....
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Home")
self.present(vc, animated: true, completion: nil)
to push users from a sign-in screen to the main app, yet with the updates here's how it looks below (iPhone currently in dark-mode)...
Some questions. What is this functionality definitively called? and how do I go about manipulating it? Say I want to remove it because right now if the user is in the main app they can swipe down and go back to the sign-in screen which would definitely cause problems.
Sign-In View Controller Code
import UIKit
import Firebase
import RealmSwift
class StartViewController: UITableViewController, UITextFieldDelegate {
#IBOutlet weak var email: UITextField!
#IBOutlet weak var password: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Check if user is already logged-in so they don't have to sign-in again
checkUserSignIn()
// Setting textfield delegates so user can press enter and go to next textfield
self.email.delegate = self
self.password.delegate = self
let uid = Auth.auth().currentUser?.uid
print(uid)
print("printing the uid here")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Add a background view to the table view
let backgroundImage = UIImage(named: "startBackground")
let imageView = UIImageView(image: backgroundImage)
self.tableView.backgroundView = imageView
imageView.contentMode = .scaleAspectFill
}
// Check if user is already signed-in, if so push to main app
func checkUserSignIn() {
Auth.auth().addStateDidChangeListener({ (auth, user) in
if (user != nil) {
Database.database().reference().child("users").child((user?.uid)!).observeSingleEvent(of: .value, with: { snapshot in
if snapshot.exists() {
print("user is logged in")
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Home")
vc.modalPresentationStyle = .overCurrentContext
self.present(vc, animated: true, completion: nil)
}
})
}
})
}
#IBAction func login(_ sender: Any) {
if self.email.text == "" || self.password.text == "" {
//Alert to tell the user that there was an error because they didn't fill anything in the textfields because they didn't fill anything in
let alertController = UIAlertController(title: "Error", message: "Please enter an email and password.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
} else {
Auth.auth().signIn(withEmail: self.email.text!, password: self.password.text!) { (user, error) in
if error == nil {
//Print into the console if successfully logged in
print("You have successfully logged in")
// Proceed To App
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "home") {
} else {
print("Problem sending user into nature app")
}
}
} else {
//Tells the user that there is an error and then gets firebase to tell them the error
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
#IBAction func createAccount(_ sender: Any) {
// Check user has entered text into fields
guard let email = email.text, email != "",
let password = password.text, password != ""
else {
// Throw alert message to user if fields are empty
let alert = UIAlertController(title: "Registration Error", message: "Please make sure you filled in all of the boxes to complete registration!", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alert.addAction(okAction)
present(alert, animated: true, completion: nil)
return
}
// Register a new user on Firebase
Auth.auth().createUser(withEmail: email, password: password, completion: { (user, error) in
// Throw registration error / Account could already exist
if let error = error {
let alert = UIAlertController(title: "Registration Error", message: error.localizedDescription, preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alert.addAction(okAction)
self.present(alert, animated: true, completion: nil)
return
}
guard let userID = user?.user.uid else {
return
}
// Database reference
let databaseRef = Database.database().reference()
// Set user information to firebase data structure
let userInfo = fireUsersData(email: email, profPicString: "", uid: userID)
databaseRef.child("users").child(userID).updateChildValues(userInfo.getUserDictionary(), withCompletionBlock: { (err, databaseRef) in
let UserToAdd = realmUserData()
UserToAdd.email = email
UserToAdd.uid = userID
//UserToAdd.saveDataToRealm()
if err != nil {
// Throw error is problem completeting
let alert = UIAlertController(title: "Error", message: (err?.localizedDescription)! as String, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
})
})
// Dismiss keyboard
self.view.endEditing(true)
// Proceed To App
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "home") {
} else {
print("Problem sending user into nature app")
}
}
}
// END OF FILE
}
Before presenting your ViewController give this option:
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Home")
vc.modalPresentationStyle = .overCurrentContext
self.present(vc, animated: true, completion: nil)
For ignoring dark mode style in didFinishLaunchingWithOptions write this:
if #available(iOS 13.0, *) {
window?.overrideUserInterfaceStyle = .light
}
UPDATE: Replace present to this code:
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Home") as! UITabBarController
UIApplication.shared.keyWindow?.rootViewController = vc

how to compare entered text against a string in terms of a password to trigger a new segue

I've got a application that is running and has segues that have questions on them and passes the data from one segue to another.
I need to add a password to my final button that triggers the the event of passing the data to the last view controller and showing the data to the person that holds the password.
I have the code that passes the code to the last page and I have the code that passes the alert to the user to enter the password.
my issue is if I have the thing for the segue before the alert the page loads and it doesn't matter if the pass word is entered or not. if the thing for the segue is after the alert nothing happens no matter what's entered in the text box.
#IBAction func DataReveal(_ sender: UIButton)
{
ID = ID2.text
date = date2.text
Answer1 = answ1.text
Answer2 = answ2.text
switch sender.tag
{
case 1: send = "Thanks"
default: print("No Selection")
}
let alertController = UIAlertController(title: "Password check", message: "Enter Password to see collected data", preferredStyle: .alert)
alertController.addTextField
{
textField in
textField.placeholder = "Enter Password"
textField.isSecureTextEntry = true
}
let confirmActionBtn = UIAlertAction(title: "OK", style: .default)
{
[weak alertController] _ in
guard let alertController = alertController, let textField = alertController.textFields?.first else
{
return
}
print("Password is \(String(describing: textField.text))")
//Just compare Entered String in textfield with your original password password
//if password is matched push or segue your required controller
}
alertController.addAction(confirmActionBtn)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
self.performSegue(withIdentifier: "Link6", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "Link6", let destination = segue.destination as? DataviewController
{
destination.Answer2 = self.Answer2
destination.Answer1 = self.Answer1
destination.ID = self.ID
destination.date = self.date
destination.send = self.send
}
}
I've made the changes as mentioned in one of the answers that was provided, I've tried to run the code but there is still another issue because its still not comparing the textfield to the password string variable and when the password is entered there isn't any perform segue movement.
#IBAction func DataReveal(_ sender: UIButton)
{
ID = ID2.text
date = date2.text
Answer1 = answ1.text
Answer2 = answ2.text
switch sender.tag
{
case 1: send = "current data collected"
default: print("No Selection")
}
let alertController = UIAlertController(title: "Password check", message: "Enter Password to see collected data", preferredStyle: .alert)
alertController.addTextField
{
textField in
textField.placeholder = "Enter Password"
textField.isSecureTextEntry = true
}
let confirmActionBtn = UIAlertAction(title: "OK", style: .default)
{
[weak alertController] _ in
guard let alertController = alertController, let textField = alertController.textFields?.first else
{
return
}
print("Password is \(String(describing: textField.text))")
func performSegue(withIdentifier identifier: String, sender: Any?) -> Bool
{
if identifier == "Link6"
{
if (textField.text == self.password)
{
return true
}
}
return false
}
}
alertController.addAction(confirmActionBtn)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
//self.performSegue(withIdentifier: "Link6", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "Link6", let destination = segue.destination as? DataviewController
{
destination.Answer2 = self.Answer2
destination.Answer1 = self.Answer1
destination.ID = self.ID
destination.date = self.date
destination.send = self.send
}
}
This is done in the shouldPerformSegue method.
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if identifier == "FirstToUsersSegue" {
if (userText.text == username && passText.text == password) {
return true
}
}
return false
}
Alerts are asynchronous, as is performing segues, so this code is performing a segue and displaying an alert.
If you don't want to perform the segue until after the alert has been dismissed, you will need to put the call to performSegue(withIdentifier:sender:) inside of the confirmActionBtn handler.

Display alert in current view, and as well as Redirect to another view

I want to display alert for check new version of my app from API. And from that view if userDefault data is store so base on that I want to redirect to another view. My redirection code is work perfectly but when I add alert code so redirection doesn't work. I think alert present in "self" and that time I also try to redirect from that view so it's may create problem. Here is my code..
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateUserData() //base on userDefault redirection
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
checkNewVersion() //Alert function for API calling
}
func checkNewVersion() -> Void {
//TODO: For check App new version
WebRequester.shared.getAppNewVersion { (result, error) in
if result != nil {
if result?.value(forKey: "status") as! Bool {
let strVer = (result?.object(forKey: "data") as! NSDictionary).object(forKey: "platform_version") as! String
if UserData.getAppVersion() < strVer {
let alert = UIAlertController(title: "Alert", message: "New version of App available", preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: { (action) in
})
let AppStore = UIAlertAction(title: "App Store", style: .default, handler: { (action) in
if let url = URL(string: "itms-apps://itunes.apple.com/app/id1024941703"),
UIApplication.shared.canOpenURL(url){
UIApplication.shared.openURL(url)
}
})
alert.addAction(ok)
alert.addAction(AppStore)
self.present(alert, animated: true, completion: nil)
// OperationQueue().addOperation {
// // Put queue to the main thread which will update the UI
// OperationQueue.main.addOperation({
// self.present(alert, animated: true, completion: nil)
// })
// }
}
}
else {
if (result?.object(forKey: "data") as! NSArray).object(at: 0) as? String ?? "" == "Unauthorised access." {
Model.shared.deleteAllCoreDataRecord(entity: "CartItem")
UIApplication.topViewController()?.navigationController?.popToRootViewController(animated: true)
}
let msg = result?.value(forKey: "data") as! [String]
Model.shared.showAlert(title: "Error", msg: msg[0], controller: self)
}
}
else {
Model.shared.showAlert(title: "Error", msg: error?.localizedDescription ?? "Something went wrong at add new address", controller: self)
}
}
}
func updateUserData() -> Void {
if UserData.getAppVersion() == "1.0" {
if UserData.getUserData() != nil {
//TODO: check for user Updated data
let params = ["mobile":UserData.getUserMobile()] as [String : Any]
let propic = UIImage(named: "temp")
weak var objWeek = self
Model.shared.showActivity(WithTouchEnable: false,controller: self)
WebRequester.shared.customerSignup(params: params as NSDictionary, proImg: propic!){ (result,error) -> Void in
Model.shared.HideActivity(controller: self)
if (error == nil) {
print("login result:",result ?? "")
//handle response of sign up
let statusstr = result?["status"] as! Bool
if (statusstr == false) {
//This condition for pepsi welcome offer is expire or not
let user = result!["user_info"] as! NSDictionary
self.storeUserData(user: user)
if UserData.getUserMobileNumVerify() == "No" {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let registerScreen = storyboard.instantiateViewController(withIdentifier: "UserRegisterPhoneVC") as! UserRegisterPhoneVC
objWeek?.navigationController?.pushViewController(registerScreen, animated: true)
}
else {
if UserData.getPepsiOfferRedim() == "1" || UserData.getPepsiOfferRedim() == "2" {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let offerScreen = storyboard.instantiateViewController(withIdentifier: "OfferViewController") as! OfferViewController
objWeek?.navigationController?.pushViewController(offerScreen, animated: true)
}
else {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let promoScreen = storyboard.instantiateViewController(withIdentifier: "PromotionViewController") as! PromotionViewController
objWeek?.navigationController?.pushViewController(promoScreen, animated: true)
}
}
}
}
}
else {
Model.shared.showAlert(title: "Error", msg: (error?.localizedDescription)!, controller: self)
}
}
}
}
}
To achieve this , you need to click on alert OK button then only it will automatically navigate to other controller , without this not possible .
Here is code :
Alert controller block help you to achieve this :
//show an alert and navigate to previous controller
let alertController: UIAlertController = UIAlertController(title: "Password updatd", message: "your alert message", preferredStyle: .alert)
let okAction: UIAlertAction = UIAlertAction(title: "OK", style: .default) { action -> Void in
//Redirect to new viewcontroler
let newVC = self.storyboard.instantiateViewcontroller(identifier: "newvc") as? NewVC
self.navigationController?.pushViewController(newVC,animated: true)
}
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)
Feel free to comment. Thanks

Missing argument for parameter 'sender' in call

I always get this error and I don't know what else to type in.
Do you guys know what's going on?
#IBAction func loginAction(sender: AnyObject)
{
let email = self.emailTextField.text
let password = self.passwordTextField.text
if email != "" && password != ""
{
FIREBASE_REF.authUser(email, password: password, withCompletionBlock: { (error, authData) -> Void in
if error == nil
{
NSUserDefaults.standardUserDefaults().setValue(authData.uid, forKey: "uid")
print("Logged in")
self.logoutButton.hidden = false
self.performSegueWithIdentifier(String, sender: AnyObject?)
self.presentViewController(HomeViewController, animated: true, completion: nil)
}
else
{
print(error)
}
})
}
else
{
let alert = UIAlertController(title: "Error", message: "Enter Email and Password", preferredStyle: .Alert)
let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
}
}
#IBAction func logoutAction(sender: AnyObject)
{
CURRENT_USER?.unauth()
NSUserDefaults.standardUserDefaults().setValue(nil, forKey: "uid")
self.logoutButton.hidden = true
}
}
The error is at the line
self.presentViewVontroller(HomeViewController...
I already created a Segue in the storyboard.
if you have created a Segue. firstly select segue and set identifier of Segue.
then perform segue like this
self.performSegueWithIdentifier(identifier, sender: nil)
No need to write this line
self.presentViewController(HomeViewController, animated: true, completion: nil)

Resources