Segues not executing when run using Swift and Parse - ios

So I've set up my app to determine if there is a user and what to do if there is or is not. Also if they have verified their account (via phone number and sms) my issue is that when I run the app nothing happens. It loads and then just doesn't perform any of the segues. All segue identifiers are named correctly. currentUser variable has a value but numberIsVerified has no value. Im sure that has something to do with it but not sure what or how to fix it.
Code to determine where to take the user:
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
var currentUser = PFUser.currentUser()
if currentUser == nil || currentUser!["phoneNumberVerified"] == nil {
performSegueWithIdentifier("showInitialView", sender: self)
} else {
if let numberIsVerified = currentUser!["phoneNumberVerified"] as? Bool {
if currentUser != nil && numberIsVerified == false {
performSegueWithIdentifier("showVerifyUserView", sender: self)
} else if currentUser != nil && numberIsVerified == true {
performSegueWithIdentifier("showMyEventsView", sender: self)
} else {
performSegueWithIdentifier("showInitialView", sender: self)
}
}
}
}
}

You can only use performSegueWithIdentifier when your view is fully loaded. So you can't segue from viewDidLoad. To fix this, move your segue to viewDidAppear:
override func viewDidAppear(animated: Bool) {
}
update: i created a simple application that performs the segue for you to compare your code to:
download project

Related

Swift Firebase: how to check user is verified after send email?

After creating account i sending an email with verification link:
func sendVerificationMail() {
if self.authUser != nil && !self.authUser!.isEmailVerified {
self.authUser!.sendEmailVerification(completion: { (error) in
// TODO Notify user email was sent or not because of error
})
} else {
// TODO Notify everything is OK
}
}
And in other place i checking it confirmed:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if Auth.auth().currentUser != nil && Auth.auth().currentUser!.isEmailVerified {
self.performSegue(withIdentifier: "toMainScreen", sender: self)
} else {
self.performSegue(withIdentifier: "notLoggedView", sender: self)
}
}
Even if confirmed, i always go to notLoggedView. Somebody can explain why?
I have faced the similar issue and to solve it I have to reload the profile. Try this.
func loginUser() {
Auth.auth().currentUser?.reload(completion: { (error) in
if let error = error {
print(error)
} else {
if Auth.auth().currentUser != nil && Auth.auth().currentUser!.isEmailVerified {
self.performSegue(withIdentifier: "toMainScreen", sender: self)
} else {
self.performSegue(withIdentifier: "notLoggedView", sender: self).
}
}
})
}
Also, instead of writing Auth.auth().currentUser every time you can store that in a variable. And, you can use this function wherever you want.
if let authUser = Auth.auth().currentUser { //You can also get current user like this in a safe way
//Do your stuff here
}

prepareForSegue called before performSegue

I am trying to perform a segue that passes a number of variables to the next view including one variable, currentID, which is retrieved from a parse database. performSegue should not be called until after currentID has been set to the currentID downloaded from the database. However, when I run the code, currentID ends up being an empty string when it is passed to the next view.
Here is my code called by the Button:
#IBAction func submitButtonPressed(_ sender: Any) {
let point = PFGeoPoint(latitude:0.0, longitude:0.0)
let testObject = PFObject(className: "Person")
testObject["inputAmount"] = inputAmount
testObject["outputAmount"] = outputAmount
testObject["inputCurrency"] = inputCurrency
testObject["outputCurrency"] = outputCurrency
testObject["location"] = point
testObject.saveInBackground { (success, error) -> Void in
// added test for success 11th July 2016
if success {
print("Object has been saved.")
self.currentID = String(describing: testObject.objectId!)
if(self.currentID != ""){
self.performSegue(withIdentifier: "mainToListSegue", sender: self)
}
} else {
if error != nil {
print (error)
} else {
print ("Error")
}
}
}
}
And here is the prepareForSegue method:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let listViewController = (segue.destination as! UINavigationController).viewControllers[0] as! ListViewController
listViewController.inputCurrency = inputCurrency
listViewController.outputCurrency = outputCurrency
listViewController.inputAmount = inputAmount
listViewController.outputAmount = outputAmount
listViewController.currentID = currentID
listViewController.cellContent = cellContent
}
To achieve your needs, you MUST connect your segue between viewcontrollers, and not from UIButton to viewcontroller.
Every time you need to prepare your segue before calling it, this is the procedure:
Then, name it and use delegate method
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mySegue" {
}
}
For navigating from one controller to another, connect your segue from view controller instead of from the button and it will work.

How can I call in Swift 3 the method prepare after the user's input has four characters?

I have the following methods:
#IBAction func postcodeTextfieldDidChanged(_ sender: UITextField) {
if (postcodeTextField.text?.characters.count == 4) {
self.postcode = postcodeTextField.text
postcodeHas4Chars = true
} else {
postcodeHas4Chars = false
}
}
And the prepare-method:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "CoffeeShopListWithPostcode" {
if (postcodeHas4Chars == true) {
if let list = segue.destination as? CoffeeShopListVC {
list.postcode = postcode
} else {
print("Data NOT Passed!")
}
}
} else { print("Id doesnt match with Storyboard segue Id")
}
}
The code works and I can send the postcode to the next ViewController, but how can I change the code to automatically call the method after the fourth input?
At the moment, the user must manually exit the input so that it can be executed.
Each time the text field's text change, check if the text is 4 characters. If it is, call performSegue(withIdentifier, sender:). Simple:
#IBAction func postcodeTextfieldDidChanged(_ sender: UITextField) {
if (postcodeTextField.text?.characters.count == 4) {
self.postcode = postcodeTextField.text
postcodeHas4Chars = true
performSegue(withIdentifier: "CoffeeShopListWithPostcode", sender: self)
} else {
postcodeHas4Chars = false
}
}
Also, remember that you connect to the editingChanged event instead of the valueChanged event.

Checking user verification using '==' on a Bool throws error using Swift and Parse

Im trying to check if there is a user and if they have verified their account (by phone number) and if there is and they have then let them continue but if there is a user that has not verified their phone number segue them to verify their phone number. My problem is that i set "phoneNumberVerified" in the Parse User class as a Bool but then I try to check using an if statement I get the error: Binary operator '==' cannot be applied to operands of type 'AnyObject!' and 'Bool'
Code to check user and verification status:
override func viewDidLoad() {
super.viewDidLoad()
var currentUser = PFUser.currentUser()
if currentUser == nil || currentUser!["phoneNumberVerified"] == nil {
performSegueWithIdentifier("showInitialView", sender: self)
} else {
if let numberIsVerified = currentUser!["phoneNumberVerified"] as? Bool {
if currentUser != nil && numberIsVerified == false {
performSegueWithIdentifier("showVerifyUserView", sender: self)
} else if currentUser != nil && numberIsVerified == true {
performSegueWithIdentifier("showMyPostsView", sender: self)
} else {
performSegueWithIdentifier("showInitialView", sender: self)
}
}
}
}
}
I think you should just try and downcast it as a Bool
override func viewDidLoad() {
super.viewDidLoad()
if let currentUser = PFUser.currentUser() {
if let numberIsVerified = currentUser["phoneNumberVerified"] as? Bool {
if numberIsVerified == false {
performSegueWithIdentifier("showVerifyUserView", sender: self)
} else if numberIsVerified == true {
performSegueWithIdentifier("showMyPostsView", sender: self)
} else {
performSegueWithIdentifier("showInitialView", sender: self)
}
}
}
}
#Paulw11 is giving you a good hint.
You'll need to compare equatable types in Swift, so if you'e storing a Boolean as part of your current parse user you'll need to cast it as such.
You can even do it in parenthesis, in place:
(currentUser!["phoneNumberVerified"] as! Bool)
I don't recall exactly how Parse stores bools and if the types are directly compatible but that should get you on the right track. The key is the types need to be the same (or inherit from the same places in some cases) to be equitable.

performSegueWithIdentifier outside of viewDidAppear not working

I am sure this is a beginners question, but I am trying to perform a Segue if the users of my application are logged into Facebook, or if they do in the initial screen. In the viewDidAppear function, I test if they are already logged in, and if they are, the segue works just fine. But in my other function, is does absolutely nothing (not even an error).
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if (PFUser.currentUser() == nil) {
//...//
} else {
print("User already logged in")
self.performSegueWithIdentifier("mainMenuSegue", sender: self) // This one is Working
}}
func logInViewController(logInController: PFLogInViewController, didLogInUser user: PFUser) -> Void {
print("We just logged you in!")
if PFUser.currentUser()!["First_Name"] == nil {
returnUserData() } else {
print(NSThread.isMainThread()) //Returning True
self.performSegueWithIdentifier("mainMenuSegue", sender: self)// This one is NOT Working
}
}
What am I doing wrong?
In iOS 6 and later it´s possible: You have to implement the method in the controller and return true or false
if you return false segue will fail to goto destination.
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
in swift
override func shouldPerformSegueWithIdentifier(identifier: String!, sender: AnyObject!) -> Bool {
//todo
}

Resources