So I am creating an iOS application and want to allow users to log in and out/register. I am doing this using core Data and currently my program allows users to register, but the data isn't saved so when they try and log in, it says incorrect username/password, in other words, the program isn't recognizing the fact that the user already input their information when creating/registering their account and as a result cannot load the information they input and won't allow the user to log in. This is the code I have for when a user clicks the register button - please help:
import UIKit
import CoreData
class RegisterPageViewController: UIViewController {
#IBOutlet weak var userEmailTextField: UITextField!
#IBOutlet weak var userPasswordTextField: UITextField!
#IBOutlet weak var confirmPasswordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func registerButtonTapped(sender: AnyObject) {
let userEmail = userEmailTextField.text
let userPassword = userPasswordTextField.text
let userConfirmPassword = confirmPasswordTextField.text
if (userEmail.isEmpty || userPassword.isEmpty || userConfirmPassword.isEmpty) {
displayMyAlertMessage("You haven't filled out all the fields.")
return;
}
if (userPassword != userConfirmPassword) {
displayMyAlertMessage("Passwords do not match.")
return;
}
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext!
var newUser = NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: context) as NSManagedObject
context.save(nil)
var successAlert = UIAlertController(title: "Alert", message: "Successfully registered.", preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) { action in
self.dismissViewControllerAnimated(true, completion: nil)
}
successAlert.addAction(okAction)
self.presentViewController(successAlert, animated: true, completion: nil)
}
#IBAction func haveAnAccountButtonTapped(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
func displayMyAlertMessage(userMessage:String) {
var alert = UIAlertController(title: "Alert!", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)
alert.addAction(okAction)
self.presentViewController(alert, animated: true, completion: nil)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
If you already have in your *.xcdatamodel file Entity 'Users' with Attributes 'name' and 'password', you need to store data from textField, for example:
...
var newUser = NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: context) as NSManagedObject
newUser.setValue(userEmail, forKey: "name")
newUser.setValue(userPassword, forKey: "password")
context.save(nil)
...
SWIFT 4
We Can Create A Login And SignUp In Swift 4 Using Core Data
Here I am Going to create a New project In Swift 4 With Xcode 9 And Follow Me With An Example Task For Core Data
Create New Project With Select Use CoreData
Create an Entity -User
Add fields - name, age,password,email….Plz Select All the fields type with String
Design Storyboard With Apropriate objects….
Create Login,signup,UserDetails,logout VC’s
Import CoreData For Apropriate Classes
For Connect Views We can Use StoryboardId And Segue For the Views
Create LoginVc
import UIKit
import CoreData
class LoginViewController: UIViewController {
#IBOutlet var nameTextCheck: UITextField!
#IBOutlet var passwordTextCheck: UITextField!
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func signUPButtonAction(_ sender: Any) {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "User")
let searchString = self.nameTextCheck.text
let searcghstring2 = self.passwordTextCheck.text
request.predicate = NSPredicate (format: "name == %#", searchString!)
do
{
let result = try context.fetch(request)
if result.count > 0
{
let n = (result[0] as AnyObject).value(forKey: "name") as! String
let p = (result[0] as AnyObject).value(forKey: "password") as! String
// print(" checking")
if (searchString == n && searcghstring2 == p)
{
let UserDetailsVc = self.storyboard?.instantiateViewController(withIdentifier: "UserDetailsViewController") as! UserDetailsViewController
UserDetailsVc.myStringValue = nameTextCheck.text
self.navigationController?.pushViewController(UserDetailsVc, animated: true)
}
else if (searchString == n || searcghstring2 == p)
{
// print("password incorrect ")
let alertController1 = UIAlertController (title: "no user found ", message: "password incorrect ", preferredStyle: UIAlertControllerStyle.alert)
alertController1.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertController1, animated: true, completion: nil)
}
}
else
{
let alertController1 = UIAlertController (title: "no user found ", message: "invalid username ", preferredStyle: UIAlertControllerStyle.alert)
alertController1.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertController1, animated: true, completion: nil)
print("no user found")
}
}
catch
{
print("error")
}
}
}
Create SignUpVc
import UIKit
import CoreData
class SignUpViewController: UIViewController {
#IBOutlet var nameText: UITextField!
#IBOutlet var passwordText: UITextField!
#IBOutlet var ageText: UITextField!
#IBOutlet var emailText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func SignUPAction(_ sender: Any) {
if isValidInput(Input: nameText.text!)
{
if isPasswordValid(passwordText.text!)
{
if isValidEmail(testStr: emailText.text!)
{
let _:AppDelegate = (UIApplication.shared.delegate as! AppDelegate)
let context:NSManagedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let newUser = NSEntityDescription.insertNewObject(forEntityName: "User", into: context) as NSManagedObject
newUser.setValue(nameText.text, forKey: "name")
newUser.setValue(passwordText.text, forKey: "password")
newUser.setValue(emailText.text, forKey: "email")
newUser.setValue(ageText.text, forKey: "age")
do {
try context.save()
} catch {}
print(newUser)
print("Object Saved.")
let alertController1 = UIAlertController (title: "Valid ", message: "Sucess ", preferredStyle: UIAlertControllerStyle.alert)
alertController1.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertController1, animated: true, completion: nil)
let UserDetailsVc = self.storyboard?.instantiateViewController(withIdentifier: "logoutViewController") as! logoutViewController
self.navigationController?.pushViewController(UserDetailsVc, animated: true)
}else
{
print("mail check")
let alertController1 = UIAlertController (title: "Fill Email id", message: "Enter valid email", preferredStyle: UIAlertControllerStyle.alert)
alertController1.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertController1, animated: true, completion: nil)
}
}
else
{
print("pswd check")
let alertController1 = UIAlertController (title: "Fill the password ", message: "Enter valid password", preferredStyle: UIAlertControllerStyle.alert)
alertController1.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertController1, animated: true, completion: nil)
}
}
else
{
print("name check")
let alertController1 = UIAlertController (title: "Fill the Name ", message: "Enter valid username", preferredStyle: UIAlertControllerStyle.alert)
alertController1.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertController1, animated: true, completion: nil)
}
}
func isValidInput(Input:String) -> Bool
{
let RegEx = "\\A\\w{3,18}\\z"
let Test = NSPredicate(format:"SELF MATCHES %#", RegEx)
return Test.evaluate(with: Input)
}
func isPasswordValid(_ password : String) -> Bool{
let passwordTest = NSPredicate(format: "SELF MATCHES %#", "^(?=.*[a-z])(?=.*[$#$#!%*?&])[A-Za-z\\d$#$#!%*?&]{3,}")
return passwordTest.evaluate(with: password)
}
func isValidEmail(testStr:String) -> Bool {
// print("validate calendar: \(testStr)")
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
let emailTest = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailTest.evaluate(with: testStr)
}
}
Create UserDetailsVC
import UIKit
import CoreData
class UserDetailsViewController: UIViewController {
#IBOutlet var nameText: UITextField!
#IBOutlet var ageText: UITextField!
#IBOutlet var emailText: UITextField!
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var myStringValue : String?
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
showData()
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
func showData()
{
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "User")
request.predicate = NSPredicate (format: "name == %#", myStringValue!)
do
{
let result = try context.fetch(request)
if result.count > 0
{
let nameData = (result[0] as AnyObject).value(forKey: "name") as! String
let agedata = (result[0] as AnyObject).value(forKey: "age") as! String
let emaildata = (result[0] as AnyObject).value(forKey: "email") as! String
nameText.text = nameData
ageText.text = agedata
emailText.text = emaildata
}
}
catch {
//handle error
print(error)
}
}
}
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)*/
}
}
}
}
Line where error is:
self.passwordField.delegate = self
Code from the button:
#IBAction func unwindToRed(_ sender: Any) {
do {
try Auth.auth().signOut()
let ViewController1 = ViewController()
let ViewNavigationController = UINavigationController(rootViewController: ViewController1)
self.present(ViewNavigationController, animated: true, completion: nil)
} catch let err {
print(err)
}
}
This is the relevant homepage code:
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
var userUID: String!
var databaseRef: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
databaseRef = Database.database().reference()
self.passwordField.delegate = self
self.emailField.delegate = self
emailField.attributedPlaceholder = NSAttributedString(string: "Email",
attributes: [NSAttributedString.Key.foregroundColor: UIColor.gray])
passwordField.attributedPlaceholder = NSAttributedString(string: "Password",
attributes: [NSAttributedString.Key.foregroundColor: UIColor.gray])
}
override func viewDidAppear(_ animated: Bool) {
if let _ = KeychainWrapper.standard.string(forKey: "uid") {
self.performSegue(withIdentifier: "tohome", sender: nil)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func signInPressed(_ sender: Any) {
Auth.auth().createUser(withEmail: (emailField.text ?? ""), password: (passwordField.text ?? "")) { (user, error) in
if let _eror = error {
//something bad happning
print(_eror.localizedDescription )
let alert = UIAlertController(title: "Error", message: "Invalid Entry or Duplicate.", preferredStyle: UIAlertController.Style.alert)
let action = UIAlertAction(title: "Ok", style: .default, handler: nil)
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
}else{
//user registered successfully
print(user as Any)
if let userID = user?.uid {
KeychainWrapper.standard.set((userID), forKey: "uid")
let databaseRef = Database.database().reference()
databaseRef.child("people").child(userID).child("users").setValue(self.emailField.text!)
databaseRef.child("people").child(userID).child("postID").setValue(userID)
self.performSegue(withIdentifier: "tohome", sender: nil)
}
}
}
}
#IBAction func loginInPressed(_ sender: Any) {
Auth.auth().signIn(withEmail: (emailField.text ?? ""), password: (passwordField.text ?? "")) { (user, error) in
if let _eror = error {
//something bad happning
print(_eror.localizedDescription )
let alert = UIAlertController(title: "Error", message: "Incorrect Email or Password.", preferredStyle: UIAlertController.Style.alert)
let action = UIAlertAction(title: "Ok", style: .default, handler: nil)
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
}else{
//user registered successfully
print(user as Any)
if let userID = user?.uid {
KeychainWrapper.standard.set((userID), forKey: "uid")
self.performSegue(withIdentifier: "tohome", sender: nil) }
}
}
}
Problem is hiding in this line:
#IBAction func unwindToRed(_ sender: Any) {
do {
try Auth.auth().signOut()
let ViewController1 = ViewController() // <-- This is the problem
let ViewNavigationController = UINavigationController(rootViewController: ViewController1)
self.present(ViewNavigationController, animated: true, completion: nil)
} catch let err {
print(err)
}
}
Because you are using storyboards to create your views, you should instantiate your view controller from storyboard. To do this right please refer to Creating View Controllers from Storyboard.
If you're new to iOS development or you don't know why this is required please refer to this post which will explain instantiating view controller from storyboard vs. creating new instance.
When I run my app the output says:
terminating with uncaught exception of type NSException
when I try to do an performseguewithidentifier or a UIAlert. I am parsing my json data but when I try to either do a UIAlert or a segue when that data equals something I get this error. What am I doing wrong?
import UIKit
class registerViewController: UIViewController {
#IBOutlet weak var nameInput: UITextField!
#IBOutlet weak var emailInput: UITextField!
#IBOutlet weak var passwordInput: UITextField!
#IBOutlet weak var confirmPassInput: UITextField!
var errorGot = String()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print(self.errorGot)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func sendBtn(_ sender: UIButton) {
let name = nameInput.text
let email = emailInput.text
let password = passwordInput.text
let confirmPass = confirmPassInput.text
if(name?.isEmpty == true || email?.isEmpty == true || password?.isEmpty == true || confirmPass?.isEmpty == true){
errorMessage(msg: "Alla fält måste vara infyllda!", type: "error")
}else if(password != confirmPass){
errorMessage(msg: "Dina lösenord stämmer ej överens", type: "error")
}else{
let myUrl = URL(string: "http://mywebsitething.com/wasterace/app/storeData/registration.php?email=\(email!)&name=\(name!)&password=\(password!)")
var request = URLRequest(url:myUrl!)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request as URLRequest) {data,response,error in
if(error != nil){
print("error")
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [Any]
for jsonResult in json {
let jsonDict = jsonResult as! [String:String]
let error = jsonDict["error"]!
self.printFunc(msg: error)
}
} catch {
print("errorcath")
}
}
task.resume()
}
}
func printFunc(msg: String){
if(msg == "true"){
self.errorMessage(msg: "Invalid entry", type: "error")
}else if (msg == "false"){
self.errorMessage(msg: "You have now registered", type: "success")
}
}
func errorMessage(msg: String, type: String){
if(type == "error"){
let alert = UIAlertController(title: "Error", message: msg, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}else if (type == "success"){
let alert = UIAlertController(title: "Grattis!", message: msg, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Logga In", style: UIAlertActionStyle.default, handler: { action in
self.performSegue(withIdentifier: "toLoginRegister", sender: self)
}))
self.present(alert, animated: true, completion: nil)
}
}
}
I had the same issue and my problem solved by using :
DispatchQueue.main.async { [weak self] in
}
I mean try to put your alert in this block.
// Hope this helps you some how.
I had created a login page and registration page and saved the registered data in core data database but now I need to authenticate the user so that in order to move to another view controller.
here is my code ....
import UIKit
import CoreData
class ViewController: UIViewController {
#IBOutlet weak var usernameTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var loginButton: UIButton!
#IBOutlet weak var registerButton: UIButton!
var accounts = [Account]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
self.getAccountData()
loginButton.layer.cornerRadius = 12.0;
registerButton.layer.cornerRadius = 12.0;
usernameTextField.layer.borderWidth = 1;
usernameTextField.layer.borderColor = UIColor.darkGray .cgColor;
usernameTextField.layer.cornerRadius = 5;
usernameTextField.setValue(UIColor.lightGray, forKeyPath: "_placeholderLabel.textColor");
passwordTextField.layer.borderWidth = 1;
passwordTextField.layer.borderColor = UIColor.darkGray.cgColor;
passwordTextField.layer.cornerRadius = 5;
passwordTextField.setValue(UIColor.lightGray, forKeyPath: "_placeholderLabel.textColor");
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func registerButton(_ sender: Any) {
self.performSegue(withIdentifier: "SecondViewController", sender: nil)
return
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
_ = segue.destination as! SecondViewController
}
#IBAction func loginButton(_ sender: Any) {
if (usernameTextField.text?.isEmpty)! == true
{
let usernamealert = UIAlertController(title: "Warning", message: "Please enter username", preferredStyle: UIAlertControllerStyle.alert)
usernamealert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(usernamealert, animated: true, completion: nil)
}
if (passwordTextField.text?.isEmpty)! == true {
let passwordalert = UIAlertController(title: "Warning", message: "Please enter password", preferredStyle: UIAlertControllerStyle.alert)
passwordalert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(passwordalert, animated: true, completion: nil)
}
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Account")
do
{
let results = try context.fetch(request)
if results.count > 0
{
for result in results as! [NSManagedObject]
{
if let firstname = result.value(forKey: "firstName") as? String
{
if(usernameTextField.text == firstname)
{
if let password = result.value(forKey: "lastname") as? String
{
if(passwordTextField.text == password)
{
}else{
let passwordalert = UIAlertController(title: "Warning", message: "Wrong password", preferredStyle: UIAlertControllerStyle.alert)
passwordalert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(passwordalert, animated: true, completion: nil)
}
}
}
}
}
}
}
}
#IBAction func unwindToView(segue: UIStoryboardSegue){}
func getAccountData() {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do {
accounts = try context.fetch(Account.fetchRequest())
} catch {
print("Fetching Failed")
}
}
Try like this
call this method from viewWillAppear
self.getAccountData()
and put below code in loginButton() method After the validation done
var username = ""
var passString = ""
var checkRecord = false
for item in accounts
{
username = item.value(forKeyPath: "firstName") as! String
passString = item.value(forKeyPath: "lastname") as! String
if username == usernameTextField.text && passwordTextField.text == passString
{
checkRecord = true;
}
}
if checkRecord == true
{
//succesfull authenticate
}
else
{
//show the error message
}
PFCloud.callFunctionInBackground("updatePositions", withParameters: ["username" : username, "location" : locationTitle, "instructor" : instructorSwitch.on, "guard" : guardSwitch.on, "sup" : supSwitch.on]) {
(positions: AnyObject!, error: NSError!) -> Void in
if error == nil {
self.currentUser.setValue(self.instructorSwitch.on, forKey: (self.shortTitle + "Instructor"))
self.currentUser.setValue(self.guardSwitch.on, forKey: (self.shortTitle + "Guard"))
self.currentUser.setValue(self.supSwitch.on, forKey: (self.shortTitle + "Sup"))
self.currentUser.save(nil)
self.navigationController?.popToRootViewControllerAnimated(true)
}
else {
let errorAlert = UIAlertController (title: "Error", message: "There was an error while processing your request. This may be because the app could not connect to the internet. Please try again.", preferredStyle: UIAlertControllerStyle.Alert)
let actionCancel = UIAlertAction (title: "Dismiss", style: .Cancel, handler: nil)
errorAlert.addAction(actionCancel)
self.presentViewController(errorAlert, animated: true, completion: nil)
}
When I run the above code, my goal to is to update the Parse Objects in my Data Browser and at the same time edit the same objects in currentUser.
As it stands now, the Login VC is shown if no one is logged in (based on a boolean value in Core Data). When a user logs in they are taken to the apps Home Page (and the boolean value is changed). If they were to shutdown the app and restart, they would be taken to the Home Page rather than the Login VC. I have a "dummy" VC where the Core Data entity is updated (I know it sounds redundant but it's there for a purpose that is unrelated to my issue).
Login VC
#IBOutlet var fullName: UITextField!
#IBOutlet var password: UITextField!
#IBOutlet var helpButton: UIButton!
#IBOutlet var loginButton: UIButton!
var nameID: String!
var passwordStatus: Bool?
var username: String?
var userID: String?
var objectID: String!
var currentUser = PFUser.currentUser()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.hidesBackButton = true
checkInternetConnection()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
self.view.endEditing(true)
}
#IBAction func LoginTapped(sender: AnyObject) {
if (fullName.text.isEmpty || password.text.isEmpty) {
let alert = UIAlertView()
alert.title = "Error"
alert.message = "You have not completed the required fields!"
alert.addButtonWithTitle("Dismiss")
alert.show()
}
else {
PFUser.logInWithUsernameInBackground(fullName.text, password: password.text) {
(user: PFUser!, error: NSError!) -> Void in
if (user != nil) {
self.currentUser = user
self.currentUser.save()
//println(self.currentUser.objectForKey("username") as String!)
if (self.currentUser.objectForKey("passwordChanged") as Bool! == nil || self.currentUser.objectForKey("passwordChanged") as Bool! == false) {
self.performSegueWithIdentifier("password", sender: self)
}
else {
self.performSegueWithIdentifier("skipPassword", sender: self)
}
}
else {
let errorAlert = UIAlertController (title: "Error", message: "Profile not found. Please check your username and password.", preferredStyle: UIAlertControllerStyle.Alert)
let actionCancel = UIAlertAction (title: "Dismiss", style: .Cancel, handler: nil)
errorAlert.addAction(actionCancel)
self.presentViewController(errorAlert, animated: true, completion: nil)
}
}
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "password") {
var svc = segue.destinationViewController as AccountSetup
svc.username = fullName.text
}
else if (segue.identifier == "skipPassword") {
var svc = segue.destinationViewController as Agree
svc.password = password.text
}
}
The only place that there is a chance for the user to log out is in the app's Settings controller:
Settings VC
var choice: String!
var currentEmail: String!
var sendEmail: String!
var email: UITextField!
var listArray = NSArray (objects: "-", "-", "-", "1", "2", "3", "4", "5", "6")
var currentUser = PFUser.currentUser()
var res : NSManagedObject!
var context : NSManagedObjectContext!
override func viewDidLoad() {
super.viewDidLoad()
currentEmail = currentUser.objectForKey("email") as String!
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 4
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
switch(section) {
case 0: return 2
case 1: return 9
case 2: return 4
case 3: return 1
default: fatalError("Unknown number of sections")
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
choice = listArray.objectAtIndex(indexPath.row) as NSString
if (indexPath.row >= 3) {
performSegueWithIdentifier("positions", sender: self)
}
else if (indexPath.row == 1) {
var passwordAlert = UIAlertController (title: "Change Password", message: "For security reasons, you can not change your password through the app. We will send an email to " + currentEmail + ". If you rather us send it to another email, enter it below. Otherwise, click 'Send'.", preferredStyle: UIAlertControllerStyle.Alert)
let standardCancel = UIAlertAction (title: "Dismiss", style: .Cancel, handler: nil)
let actionSubmit = UIAlertAction (title: "Send", style: .Default) { (action) in
if (self.email.text.isEmpty) {
self.sendEmail = self.currentEmail
}
else {
self.sendEmail = self.email.text
}
PFUser.requestPasswordResetForEmailInBackground(self.sendEmail){
(success: Bool!, error: NSError!) -> Void in
if (success == true) {
let emailAlert = UIAlertController (title: "Password", message: "An email containing information on how to change your password has been sent to " + self.sendEmail + ".", preferredStyle: UIAlertControllerStyle.Alert)
emailAlert.addAction(standardCancel)
self.presentViewController(emailAlert, animated: true, completion: nil)
}
else {
let errorAlert = UIAlertController (title: "Error", message: "There was an error while processing your request. This may be because the email is invalid or the app could not connect to the internet. Please try again.", preferredStyle: UIAlertControllerStyle.Alert)
errorAlert.addAction(standardCancel)
self.presentViewController(errorAlert, animated: true, completion: nil)
}
}
}
let actionCancel = UIAlertAction (title: "Cancel", style: .Cancel, handler: nil)
passwordAlert.addTextFieldWithConfigurationHandler {
(textField) in textField.placeholder = "Email"
self.email = textField
}
passwordAlert.addAction(actionSubmit)
passwordAlert.addAction(actionCancel)
self.presentViewController(passwordAlert, animated: true, completion: nil)
}
}
#IBAction func logoutPressed (sender: AnyObject) {
PFUser.logOut()
//code to change Core Data boolean value to start on Login is here but there is no need to put it (unrelated)
tabBarController?.tabBar.hidden = true
performSegueWithIdentifier("goToLogin", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "positions") {
var svc = segue.destinationViewController as UpdatePositions;
svc.locationTitle = choice
println (choice)
}
}
Like I've mentioned before, everything works up until the app is shutdown where the authentication is lost.
Ends up that there was an error in the 1.6.0 Parse SDK. Works fine with 1.6.5.