How can I show a popup in a ViewController - ios

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)
}

Related

Login view controller don't want to dismiss after sign in

I want to ask I have a sign in view controller who don't want to dismiss after correctly add email and password. but when I try the simulator for the first time the sign in is working and directing to me to my home controller, but after I sign out. and try to sign in again, then the sign in not dismissing my sign in view controller. how is that possible? at first is working later on is not working, here I show you my code.
// this is my sign out button
#objc private func handleSignOut() {
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Log Out".localized(), style: .destructive, handler: { (_) in
self.progressHUD.show(in: self.view)
ProfileServices.shared.signOutUser { success in
if success {
self.progressHUD.dismiss(animated: true)
let signInVC = SigninViewController()
self.present(signInVC, animated: true, completion: nil)
} else {
self.progressHUD.textLabel.text = "Error"
self.progressHUD.dismiss(afterDelay: 0.4)
}
}
}))
alert.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
// this is my sign out function in ProfileServices.shared
func signOutUser(completion: #escaping (Bool) -> Void) {
AF.request(API_URL.AUTHENTICATION.LOGOUT, method: .delete, parameters: nil, encoding: URLEncoding.default, headers: HEADERS, interceptor: nil).responseData { (dataResponse) in
if dataResponse.error == nil {
let domain = Bundle.main.bundleIdentifier!
UserDefaults.standard.removePersistentDomain(forName: domain)
UserDefaults.standard.synchronize()
UserDefaults.removeToken()
completion(true)
} else {
completion(false)
}
}
}
// this is my sign in route in my sign in view controller
func routeToMainView(_ data: SigninModel.Response) {
let school = UserDefaults.getSelectedSchool()
guard let schools = data.schools?.schools else { return }
if let selectedSchool = school, let selected = schools.first(where: { $0.id == selectedSchool.id}) {
UserDefaults.saveSelectedSchool(data: selected)
let vc = MainViewController()
self.viewController?.navigationController?.setViewControllers([vc], animated: true)
} else {
if schools.count > 1 {
let vc = SwitchSchoolViewController()
self.viewController?.navigationController?.setViewControllers([vc], animated: true)
} else {
guard let selected = schools.first else { return }
UserDefaults.saveSelectedSchool(data: selected)
DispatchQueue.main.async {
let vc = MainViewController()
self.viewController?.navigationController?.setViewControllers([vc], animated: true)
}
}
}
}
// this is in my appDelegate
var root: UIViewController?
root = SigninViewController()
if UserDefaults.getToken() != nil {
root = MainViewController()
}
In logout you need to dissmiss the presented viewController.
inplace :
let signInVC = SigninViewController()
self.present(signInVC, animated: true, completion: nil)
you need to use:
self.dismiss(animated: true, completion: nil)
or pop if you will use Push.

Logic errors with password authentication code

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)

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

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