I have the following problem. I try to learn coding since a few weeks and my actually project is an Login-Page.
The concept is the following:
When I open the App, there is the Login Screen and the User can login. This works so far. After the login the user is directed to another view. There is a logout button. And here is the problem. When I click the button, the user get logged out (I proofed this by printing out the current user and got nil) and is returned again to the login screen. But when he is now clicking on the login button without or with wrong data he is getting again to the screen although it appeared the error message.
Where is my fault?
Here is my code:
import UIKit
import Parse
class ViewController: UIViewController {
func displayAlert(title:String, message:String){
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in self.dismiss(animated: true, completion: nil)}))
self.present(alert, animated: true, completion: nil)
}
#IBOutlet weak var benutzer: UITextField!
#IBOutlet weak var passwort: UITextField!
#IBAction func ButtonLogin(_ sender: Any) {
// Hier die Loginfunktion
let activityIndiaktor = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
activityIndiaktor.center = self.view.center
activityIndiaktor.hidesWhenStopped = true
activityIndiaktor.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
view.addSubview(activityIndiaktor)
activityIndiaktor.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents()
PFUser.logInWithUsername(inBackground: benutzer.text!, password: passwort.text!, block: { (user, error) in
if user == nil {
var errortext = "Unknown Error! Try again!"
if let error = error {
errortext = error.localizedDescription
}
self.displayAlert(title: "Login error", message: errortext)
}else{
print("Login done!")
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Main") as! UIViewController
self.present(viewController, animated: true, completion: nil)
// UIApplication.shared.endIgnoringInteractionEvents()
// activityIndiaktor.stopAnimating()
}
activityIndiaktor.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
return
})
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
And here for the other view:
import UIKit
import Parse
class MainViewController: UIViewController {
#IBAction func Logout(_ sender: Any) {
PFUser.logOut()
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginSeite") as! UIViewController
self.present(viewController, animated: true, completion: nil)
}
#IBOutlet weak var LabelWillkommen: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let user = String(describing: PFUser.current()!.username!)
LabelWillkommen.text = "Welcome \(user)!"
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
In your MainViewController Just change your logout button action with below code snippet
#IBAction func Logout(_ sender: Any) {
PFUser.logOut()
if PFUser.current()?.sessionToken == nil {
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginSeite") as! UIViewController
self.present(viewController, animated: true, completion: nil)
}
}
Hope this will help you
I checked everything again. I couldn't find the mistake. The Logout works but the if case still thinks, the user is logged in. Can I maybe reload the View or reload the if statement or something like that? Or other ideas?
Related
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.
After writing the log in with mail, i'm integrating social logins to my app and starting with Google signin. It now logs in automatically at app start, not if I press the Google login button. If I cancel it at pop up window it throws an Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional valueon the token line in AppDelegate`. Also logging out doesn't prevent to log in automatically again.
It was quite confusing following instruction from Firebase manual for Google login so I sure made some obvious mistake.
Here's the code so far:
AppDelegate:
// start google sign in methods
#available(iOS 9.0, *)
func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any])
-> Bool {
return GIDSignIn.sharedInstance().handle(url,
sourceApplication:options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String,
annotation: options[UIApplicationOpenURLOptionsKey.annotation])
}
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error?) {
// ...
print("User successfully signed in with Google",user)
guard let idToken = user.authentication.idToken else {
return
}
guard let accessToken = user.authentication.accessToken else {return}
let credentials = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: accessToken)
Auth.auth().signInAndRetrieveData(with: credentials) { (user, error) in
if let error = error {
print("Failed to create user with Google account", error)
return
}
print("Succesfully created new user in Firebase with Google account")
}
if let error = error {
// ...
print("User failed to sign in with Google", error)
return
}
guard let authentication = user.authentication else { return }
let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
accessToken: authentication.accessToken)
// let storyboard = UIStoryboard(name: "Main", bundle: nil)
// var mainVC = self.window?.visibleViewController as? MainNavigationController
// mainVC = storyboard.instantiateViewController(withIdentifier: "MainNavigationController") as? MainNavigationController
}
func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) {
// Perform any operations when the user disconnects from app here.
// ...
}
// end of google sign in
The Google signin should perform a segue to main menu but it doesn't.
Only at first sign in it gets to the desired vc.
Here's the Login class:
import UIKit
import Firebase
import GoogleSignIn
class LoginViewController: UIViewController, GIDSignInUIDelegate {
// outlets
#IBOutlet weak var backGroundImage: UIImageView!
#IBOutlet weak var userNameTextField: UITextField!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var confirmPasswordTextField: UITextField!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if Auth.auth().currentUser != nil {
self.performSegue(withIdentifier: "skipSegue", sender: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
setGoogleButton()
setFacebookButton()
}
// dismiss keyboard on touch outside textfields
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for txt in self.view.subviews {
if txt.isKind(of: UITextField.self) && txt.isFirstResponder {
txt.resignFirstResponder()
}
}
}
private func setGoogleButton() {
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().signIn()
}
private func setFacebookButton() {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Actions
#IBAction func newUserRegisterButton(_ sender: Any) {
if passwordTextField.text != confirmPasswordTextField.text{
let alertController = UIAlertController(title: "Password Incorrect", message: "Please re-type 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().createUser(withEmail: emailTextField.text!, password: passwordTextField.text!){ (user, error) in
if error == nil {
self.performSegue(withIdentifier: "skipSegue", sender: self)
}
else{
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 mailLogin(_ sender: UIButton) {
Auth.auth().signIn(withEmail: emailTextField.text!, password: passwordTextField.text!) { (user, error) in
if error == nil{
self.performSegue(withIdentifier: "skipSegue", sender: self)
}
else{
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 facebookLogin(_ sender: UIButton) {
}
#IBOutlet weak var signInButton: GIDSignInButton!
#IBAction func googleSignInButton(_ sender: GIDSignInButton) {
performSegue(withIdentifier: "skipSegue", sender: self)
}
#IBAction func logoutButton(_ sender: UIButton) {
}
#IBAction func skipButton(_ sender: UIButton) {
performSegue(withIdentifier: "skipSegue", sender: self)
}
}
The sign out:
#IBAction func logOutButton(_ sender: UIButton) {
// firebase auth sign out
let firebaseAuth = Auth.auth()
do {
try firebaseAuth.signOut()
} catch let signOutError as NSError {
print ("Error signing out: %#", signOutError)
}
// GSI log out
GIDSignIn.sharedInstance().signOut()
print("User successfully logged out Firebase with Google account")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initial = storyboard.instantiateInitialViewController()
UIApplication.shared.keyWindow?.rootViewController = initial
}
func signOutOverride() {
do {
GIDSignIn.sharedInstance().signOut()
try GIDSignIn.sharedInstance()?.disconnect()
// Set the view to the login screen after signing out
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initial = storyboard.instantiateInitialViewController()
UIApplication.shared.keyWindow?.rootViewController = initial
// let storyboard = UIStoryboard(name: "SignIn", bundle: nil)
// let loginVC = storyboard.instantiateViewControllerWithIdentifier("SignInVC") as! SignInViewController
// let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
// appDelegate.window?.rootViewController = loginVC
} catch let signOutError as NSError {
print ("Error signing out: \(signOutError)")
}
}
I read many posts about revoking the tokens and disconnect the user from the app, but couldn't implement those solutions as some are in obj-c and others in older swift syntax.
Anyone having same problem as me?
Thank as usual.
After many tries and error,thanks to Google's sarcastically useful documentation, I found out what the problem was. They suggest to put the sign in inside viewDidLoad()' and that obviously get's called every time the VC gets instantiated. I so Moved into the Google sign in button and left the delegate only inviewDidLoad()
It all now works as expected.
override func viewDidLoad() {
super.viewDidLoad()
GIDSignIn.sharedInstance().uiDelegate = self
setFacebookButton()
}
#IBOutlet weak var signInButton: GIDSignInButton!
#IBAction func googleSignInButton(_ sender: GIDSignInButton) {
GIDSignIn.sharedInstance()?.signIn()
performSegue(withIdentifier: "skipSegue", sender: self)
}
I have an app lets user add his image. For this I use UIImagePicker.
Please take a look at the following function:
It opens a view as a popup when image is tapped.
func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
let userDetails:Dictionary = (UserDefaults.standard.value(forKey: "myUserDetails") as? [String:Any])!
let UserID:Int = userDetails["UserID"] as! Int
let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "imager") as! imagerVC
popOverVC.UserID = UserID
self.addChildViewController(popOverVC)
popOverVC.view.frame = self.view.frame
self.view.addSubview(popOverVC.view)
popOverVC.didMove(toParentViewController: self)
popOverVC.callback = { image in
// do something with the image
self.profile_image.image = image
if let data = UIImagePNGRepresentation(image) {
//save profile image as NewUserID
UserDefaults.standard.set(data, forKey: String(UserID))
UserDefaults.standard.synchronize()
}
}
}
This is the View code that activates the camera and this view is opened as popOverVC from the code above.
import UIKit
class imagerVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var UserID:Int = 0
#IBOutlet weak var myImageView: UIImageView!
var callback : ((UIImage) -> ())?
#IBOutlet weak var btn_end: UIButton!
#IBOutlet weak var from_camera: UIBarButtonItem!
#IBOutlet weak var from_gallery: UIBarButtonItem!
#IBAction func btn_end_pressed(_ sender: UIButton) {
self.view.removeFromSuperview()
}
#IBAction func btn_closer(_ sender: UIButton) {
self.view.removeFromSuperview()
}
#IBAction func photofromLibrary(_ sender: UIBarButtonItem) {
picker.allowsEditing = false
picker.sourceType = .photoLibrary
picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
picker.modalPresentationStyle = .popover
present(picker, animated: true, completion: nil)
picker.popoverPresentationController?.barButtonItem = sender
}
#IBAction func shootPhoto(_ sender: UIBarButtonItem) {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
UserDefaults.standard.set(true, forKey: "is_selfie")
UserDefaults.standard.synchronize()
DispatchQueue.main.async {
self.picker.allowsEditing = false
self.picker.sourceType = UIImagePickerControllerSourceType.camera
self.picker.cameraCaptureMode = .photo
self.picker.modalPresentationStyle = .fullScreen
self.present(self.picker,animated: true,completion: nil)
}
} else {
noCamera()
}
}
let picker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - Delegates
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
myImageView.contentMode = .scaleAspectFit //3
myImageView.image = chosenImage //4
myImageView.layer.borderWidth = 1
myImageView.layer.masksToBounds = false
myImageView.layer.borderColor = UIColor.black.cgColor
myImageView.layer.cornerRadius = myImageView.frame.height/4
myImageView.clipsToBounds = true
callback?(chosenImage)
dismiss(animated:true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
func noCamera(){
let alertVC = UIAlertController(
title: "No Camera",
message: "Sorry, this device has no camera",
preferredStyle: .alert)
let okAction = UIAlertAction(
title: "OK",
style:.default,
handler: nil)
alertVC.addAction(okAction)
present(
alertVC,
animated: true,
completion: nil)
}
}
I have two problems. Maybe they are related.
The main problem is that after the camera view loads and the picture is taken, When I press the button Use photo, the camera does not get dismissed at once and there is a lag of about a minute till the camera view is dismissed. The callback function by the way get triggered as soon "use photo" button is pressed.
I am not sure if this is connected but I get the following warning:
Instance method 'imagePickerController(_:didFinishPickingMediaWithInfo:)' nearly matches requirement yet when i let Xcode autocorrect me the camera functionality ceases to function.
I tried wrapping the line
dismiss(animated:true, completion: nil)
in DispatchQueue.main.async to make it run on main thread but that did not work
Not sure why but lag does not occur in physical IPad, only iPhone devices
Any help rendered is greatly appreciated
this is as expected behaviour on simulators. It should not lag on device and as you said its working on device then its cool. !!!
I'm having a problem with the alert not displaying. I know it works because it prints to my console. I also tested the alertpopup in a viewDidAppear method and it worked. I've read some post and it maybe because of me trying to perform a segue and save a userdefault at the same time. I keep getting "Warning: Attempt to present... whose view is not in the window hierarchy". Any way to fix it or an explanation of what I'm doing wrong?
import UIKit
class StartMenuViewController : UIViewController
{
#IBOutlet var nameInput: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func startAction(_ sender: Any)
{
if nameInput.text == ""
{
print("This is working")
createAlert(title: "Warning", message: "Need to enter name")
}
UserDefaults.standard.set(nameInput.text, forKey: "UserName")
}
override func viewDidAppear(_ animated: Bool)
{
if let name = UserDefaults.standard.object(forKey: "UserName") as? String
{
nameInput.text = name
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func createAlert (title: String, message: String)
{
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: { (action) in
alert.dismiss(animated: true, completion: nil)
}))
self.present(alert, animated: true, completion: nil)
}
}
There are many questions on Stack concerning this issue, but none of them seem to solve the issue I'm having.
I am using ParseUI for the login and signup portion of my application. What I would like to have happen is for a UIAlertController to be presented when a user (for example) does not enter in any text in the username and password fields.
Here is the code for my MasterViewController:
class MasterViewController: UIViewController, PFLogInViewControllerDelegate,
PFSignUpViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if (PFUser.currentUser() == nil) {
var logInViewController = LoginViewController()
logInViewController.delegate = self
var signUpViewController = SignUpViewController()
signUpViewController.delegate = self
logInViewController.signUpController = signUpViewController
self.presentViewController(logInViewController, animated: true, completion: nil)
}
}
func logInViewController(logInController: PFLogInViewController,
shouldBeginLogInWithUsername username: String, password: String) -> Bool {
if (!username.isEmpty || !password.isEmpty) {
return true
} else {
let alertController = UIAlertController(title: "Failed to login.",
message: "Login Failure. Please try again.", preferredStyle: .Alert)
let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
self.presentViewController(alertController, animated: true, completion: nil)
return false
}
}
func logInViewController(logInController: PFLogInViewController,
didFailToLogInWithError error: NSError?) {
println("Failed to log in.")
}
func signUpViewController(signUpController: PFSignUpViewController,
shouldBeginSignUp info: [NSObject : AnyObject]) -> Bool {
if let password = info["password"] as? String {
return count(password.utf16) >= 8
} else {
return false
}
}
func signUpViewController(signUpController: PFSignUpViewController,
didFailToSignUpWithError error: NSError?) {
println("Failed to sign up.")
}
func logInViewController(logInController: PFLogInViewController,
didLogInUser user: PFUser) {
let installation = PFInstallation.currentInstallation()
installation["user"] = PFUser.currentUser()
installation.saveInBackground()
self.dismissViewControllerAnimated(true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func signUpViewControllerDidCancelSignUp(signUpController:
PFSignUpViewController) {
println("User dismissed signup.")
}
}
After reading another user's answer which seemed like it would be the answer, I added the following class to my workspace:
import Foundation
class AlertHelper: NSObject {
func showAlert(fromController controller: MasterViewController) {
var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert)
controller.presentViewController(alert, animated: true, completion: nil)
}
}
And then modified my method accordingly:
func logInViewController(logInController: PFLogInViewController,
shouldBeginLogInWithUsername username: String, password: String) -> Bool {
if (!username.isEmpty || !password.isEmpty) {
return true
} else {
let alertController = UIAlertController(title: "Failed to login.",
message: "Login Failure. Please try again.", preferredStyle: .Alert)
let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
var alert = AlertHelper()
alert.showAlert(fromController: self)
return false
}
}
At this point I'm not quite sure what else to do. One thought I had was to programmatically add a UILabel to my LoginViewController and SignUpViewController and change the content based on the errors (or lack thereof) for the user login and signup, but I would like to have alerts.
EDIT: This is the code in my LoginViewController. It subclassed in order to customize the appearance. The code for my SignUpViewController is almost identical.
import UIKit
import Parse
import ParseUI
class LoginViewController: PFLogInViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = ckPurple
let label = UILabel()
label.textColor = UIColor.whiteColor()
label.text = "Welcome."
label.sizeToFit()
logInView?.logo = label
// Do any additional setup after loading the view.
}
The problem is that you present a login view controller from your master view controller, which removes the master view controller from the view hierarchy. You then attempt to present an alert view controller from your master view controller, but you need to present from a view controller in the view hierarchy. Try presenting the alert from your login view controller instead.
loginController.presentViewController(alertController, animated: true, completion: nil)