I am currently working on a social media app and so far I have been able to make a LoginViewController & a SignUpVIewController, and have it where when the user taps on the Sihn Up Button on the LoginViewController it takes them to the SignUpViewCOntroller. Right now I am currently trying to have it where on the SignUpViewController if not all required fields are filled out then the app will display an alert. However, every time I run the app the alert doesn't show up on the simulator screen.
My code for the SignUpViewController is as follows:
import UIKit
import Parse
class SignUpViewController: UIViewController
{
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var usernameTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var confirmPasswordFieldText: UITextField!
#IBOutlet weak var signUpButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func signUpButtonTapped(_ sender: UIButton)
{
let username = usernameTextField.text
let password = passwordTextField.text
let email = emailTextField.text
let confirmpw = confirmPasswordFieldText.text
if username == "" || password == "" || email == "" || confirmpw == ""
{
let alert = UIAlertController(title: "Error", message: "Please fill out all required fields", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default,handler: nil))
present(alert, animated: true, completion: nil)
return
}
let newUser = User(username: username!, password: password!, email: email!)
}
}
class User
{
var username: String
var password: String
var email: String
init(username: String, password: String, email: String) {
self.username = username
self.password = password
self.email = email
}
}
Essentially when I tap the SignUp button on my SignUpViewController while leaving all the fields blank it still takes me to the next view controller (which I plan to have been the profile creation view controller), instead of showing the alerts. All the buttons are connected to the correct spots. Would greatly appreciate it if anyone can help me fix this.
It appears (I'm making an assumption here but without a screenshot of your storyboard it is hard to be certain) you may have connected the button in your storyboard to the next view controller via a segue. If that's the case then it would automatically move to the next view controller. So, here you should remove your segue inside the storyboard and programatically navigate to the next screen using your #IBAction method.
Also, unrelated to this, but #INFINITE's comment is also a good observation. You should probably use a guard statement here like below:
#IBAction func signUpButtonTapped(_ sender: UIButton) {
guard let username = usernameTextField.text,
let password = passwordTextField.text,
let email = emailTextField.text,
let confirmpw = confirmPasswordFieldText.text else {
// It may be a good idea to refactor this bit into a separate method
let alert = UIAlertController(title: "Error", message: "Please fill out all required fields", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
return
}
let newUser = User(username: username, password: password, email: email)
// present the next view controller here
let storyboardInstance = UIStoryboard.init(name: "YOUR_STORYBOARD_NAME", bundle: Bundle.main)
if let profileViewController = storyboardInstance.instantiateViewController(withIdentifier: "YOUR_VIEWCONTROLLER_STORYBOARD_ID") {
// set whatever your have to on the profile view controller here
// profileViewController.user = newUser
// then,
// either push the next view controller
// navigationViewController?.pushViewController(profileViewController, animated: true)
// or present it
// present(profileViewController, animated: true)
// or do whatever else is needed
}
}
Related
Login page doesn't really check for if user is stored in core data and will just go ahead with the segue. It should login only if user is registered in core data else will input error and to go register but register seems to work correctly tho I followed some guides online
I have attached the code please check and give me some suggestion to achieve my task
LoginVC
import UIKit
import CoreData
class LoginVC: UIViewController {
#IBOutlet weak var username: UITextField!
#IBOutlet weak var password: UITextField!
var credits = 200.0
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view
fetchData()
}
#IBAction func login(_ sender: Any) {
for acc in userList {
if acc.username == username.text && acc.password == password.text {
currentUser = username.text!
try! context.save()
//performSegue(withIdentifier: "DisplayShop1", sender: nil)
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let next = storyBoard.instantiateViewController(identifier: "DisplayShop1") as! ListingShopVC
next.modalPresentationStyle = .fullScreen
self.present(next, animated: true, completion: nil)
}
else if username.text != acc.username || password.text != acc.password || password.text == "" || username.text == "" {
let alert = UIAlertController(title: "Alert", message: "Please enter the correct credentials", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "hellothere" {
let ve = segue.destination as! ListingShopVC
ve.creditsss = credits
}
}
func fetchData(){
userList = try! context.fetch(User.fetchRequest())
}
}
RegisterVC
import UIKit
import CoreData
class RegisterVC: UIViewController {
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var userList: String = ""
#IBOutlet weak var username: UITextField!
#IBOutlet weak var cpassword: UITextField!
#IBOutlet weak var password: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func register(_ sender: Any) {
if username.text != ""{
if password.text != "" {
if password.text == cpassword.text {
let newu = User(context: context)
newu.username = username.text
newu.password = password.text
newu.credit = 200.0
try! context.save()
self.navigationController?.popViewController(animated: true)
}
else {
let alert = UIAlertController(title: "Alert", message: "Please enter values correctly", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
present(alert, animated: true, completion: nil)*/
}
}
}
}
With using firebase as well. My signup is working well and it registers users. But my login was working fine at start but now it allows anyone to go to the next view(login).
Here's my code:
SignInVC..
import UIKit
import Firebase
class SignInVC: UIViewController {
#IBOutlet weak var emailTF: UITextField!
#IBOutlet weak var passwordTF: UITextField!
#IBAction func onSignInTapped(_ sender: Any) {
guard let email = emailTF.text,
email != "",
let password = passwordTF.text,
password != ""
else {
AlertController.showAlert(self, title: "Missing Information", message: "Please fill in username and password")
return
}
Auth.auth().signIn(withEmail: email, password: password) { (user, error) in
guard error == nil
else {
AlertController.showAlert(self, title: "Oops!", message: error!.localizedDescription)
return
}
guard let user = user else {return}
print(user.email ?? "Missing email address")
print(user.displayName ?? "Missing name")
print(user.uid)
self.performSegue(withIdentifier: "signInSegue", sender: nil)
}
}
//remove keyboard
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
AlerControllerVC
import UIKit
import Firebase
class AlertController {
static func showAlert(_ inViewController: UIViewController, title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(action)
inViewController.present(alert, animated: true, completion: nil)
}
}
I tried many was and rewrote it again but wont work correct again, when executed it says:
".SignInVC: 0x7fd99c208280> whose view is not in the window hierarchy!"
Please check if your segue is from button to ViewController or from ViewController to ViewController. if it is from button to VC then it does not depend upon the code you wrote
My current project has a login page, but I find that the user must enter their username and password again when they log in. How do I make it easier for them, by implementing "remember username and password" functionality and adding Touch ID?
My code is as follows:
import UIKit
import Firebase
class LoginViewController: UIViewController {
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView = UIImageView(frame: view.bounds)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.image = #imageLiteral(resourceName: "background")
imageView.center = view.center
view.addSubview(imageView)
self.view.sendSubview(toBack: imageView)
}
//Outlets
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
//Login Action
#IBAction func loginAction(_ sender: AnyObject) {
if self.emailTextField.text == "" || self.passwordTextField.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.emailTextField.text!, password: self.passwordTextField.text!) { (user, error) in
if error == nil {
//Print into the console if successfully logged in
print("You have successfully logged in")
//Go to the HomeViewController if the login is sucessful
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
self.present(vc!, animated: true, completion: nil)
} 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)
}
}
}
}
you have a couple of ways to save your user Credentials. Most common way is to save those in Keychain.
KeyChain Swift
After that you can user your touchID authentication, by calling the default methods to implement this. Here is a nice tutorial how you should do it:
Touch ID for Local Authentication
I have a login view controller that users need to type username and password in order to see the homepage. Now the users must type in the username and password every single time, which isn't convenient. I need to have a check box for "remember username" and "remember password" so that users can choose wether or not they would like to have their username of password stored the next time they login.
Any good way to do that? Or do I have to use Keychain, which according to many people is the best way?
My code is as follows:
import UIKit
import Firebase
class LoginViewController: UIViewController {
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView = UIImageView(frame: view.bounds)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.image = #imageLiteral(resourceName: "background")
imageView.center = view.center
view.addSubview(imageView)
self.view.sendSubview(toBack: imageView)
activityIndicator.hidesWhenStopped = true
}
//Outlets
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
//Login Action
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
#IBAction func loginAction(_ sender: AnyObject) {
self.activityIndicator.startAnimating()
if self.emailTextField.text == "" || self.passwordTextField.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)
self.activityIndicator.stopAnimating()
} else {
Auth.auth().signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!) { (user, error) in
if error == nil {
//Print into the console if successfully logged in
print("You have successfully logged in")
//Go to the HomeViewController if the login is sucessful
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
self.present(vc!, animated: true, completion: nil)
self.activityIndicator.stopAnimating()
} 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)
self.activityIndicator.stopAnimating()
}
}
}
}
}
Below are some ways in which you can stored your credential:
NSUserDefault
plist
KeyChain Store
Local Database (SQLite)
CoreData
From above all, NSUserDefault and Keychain are best and easy way to use.
NSUserDefault:
For Storing into Default:
UserDefaults.standard.set(true, forKey: "Key") //Bool
UserDefaults.standard.set(1, forKey: "Key") //Integer
UserDefaults.standard.set("TEST", forKey: "Key") //setObject
Getting from Defaults:
UserDefaults.standard.bool(forKey: "Key")
UserDefaults.standard.integer(forKey: "Key")
UserDefaults.standard.string(forKey: "Key")
KeyChain: . Checkout this demo for keychain.
You can use any one of the below approach -
NSUserDefaults
KeychainWrapper
NSURLCredential
Reference URL iOS: How to store username/password within an app?
Keychain is the most secure place to store the raw password.It means better than any other places.
You can use KeychainWrapper which is providing from Appleās Keychain Services Programming Guide.
I'm new in swift, and I've been searching this answer for weeks, but I still haven't found it:( What I'm building is a master-detail app. It is a reminders app.The user is able to edit those reminders in the detail view, but the problem comes when I try to pass the edited data back to the master view, and add it to an array of arrays that I use as the database. I've tried with an unwind segue, but I don't know how to add in the right place the data that I have passed back. I would really appreciate your help!
//MAIN VIEW
var addMoneyArray = [[Int]]()
class GonMainTableViewController: UITableViewController {
//MARK: - VARIABLES
var recivedData : Int?
//MARK. - IB OUTLETS
#IBOutlet var tableView1: UITableView!
#IBAction func unwindViewController(segue: UIStoryboardSegue){
if(segue.sourceViewController .isKindOfClass(GonDetailViewController))
{
let view2 : GonDetailViewController = segue.sourceViewController as! GonDetailViewController
recivedData = view2.passTxtFieldValue
}
}
enter code here
//VIEW2
class GonDetailViewController: UIViewController {
var passTxtFieldValue : Int?
#IBAction func addBtn(sender: AnyObject) {
var returnMoney = Int(addMoneyTxtField.text!)
returnMoney = passTxtFieldValue
let alertController = UIAlertController(title: "Awesome!", message: "Succesfully saved your data!", preferredStyle: .Alert)
let takePhotoAction = UIAlertAction(title: "OK", style: .Default) { (Alert) -> Void in
self.performSegueWithIdentifier("returnToMain", sender: self)
}
alertController.addAction(takePhotoAction)
presentViewController(alertController, animated: true, completion: nil)
}