The code continually segues into the next view controller...even with performSegueWithIdentifier() commented out. It doesn't matter if the text fields are blank (which should prompt up an alert) or if the username/password is entered correctly, it just segues anyway.
I've tried Clean -> Build -> Run, as well as removing the view controller in Storyboard and re-adding a new one. What's the issue here?
PFUser.logInWithUsernameInBackground(userEmail, password: userPassword) {
(user: PFUser?, error: NSError?) -> Void in
//If user is found in Parse, log in
if user != nil {
var successAlert = UIAlertView(title: "Success", message: "Logged In", delegate: self, cancelButtonTitle: "OK")
successAlert.show()
//Transition to FacebookViewController
//self.performSegueWithIdentifier("loginToFacebookSegue", sender: self)
}
//Display warning - incorrect login
var warningAlert = UIAlertView(title: "Try again", message: "Username/password incorrect", delegate: self, cancelButtonTitle: "Dismiss")
warningAlert.show()
}
Your problem is that since your segue is attached to a UIButton, it is automatically called when the button is pressed. Your block is never really getting called. To fix this, drag your connection from view controller to view controller. Make sure you are zoomed out in the storyboard, then just create the connection (option dragging from a black spot in the view controller itself not the button). Make sure to give your segue an identifier.
Then call performSegueWithIdentifier when you need to run the segue.
Related
This is i have written in viewDidLoad.
if DBSession.shared().isLinked() {
print("already linked")
initDropboxRestClient()
}
else
{
print("connecting2")
DBSession.shared().link(from: self)
initDropboxRestClient()
}
and function initDropboxRestClient() is written below.
func initDropboxRestClient() {
dbRestClient = DBRestClient(session: DBSession.shared())
dbRestClient.delegate = self
dbRestClient.loadMetadata("/")
}
The problem is i have two view controllers for displaying dropbox file names, the first view controller is calling the delegate methods and displaying filename and folder names perfectly. But the second one isn't.
In the second view controller,
I observed that if i scroll my tableview in second view controller up and down then the delegate methods get called immediately and once it is linked next time the methods are called immediately.
So for the first time delegate methods are not getting called in my second dropbox view controller thats my problem here. Thanks in advance.
The restClient delegate methods are as follows.
func restClient(_ client: DBRestClient!, loadedMetadata metadata: DBMetadata!) {
for file in metadata.contents
{
dbMetadataArray.append(file as! DBMetadata)
fileNamesArray.append((file as AnyObject).filename)
}
tableView.reloadData()
self.myActivityIndicator.stopAnimating()
self.myActivityIndicator.hidesWhenStopped = true
}
func restClient(_ client: DBRestClient!, loadMetadataFailedWithError error: Error!) {
print("in loadMetadataFailedWithError method in dropbox email view controller")
print("Error dscription = %#",[error.localizedDescription])
let alert = UIAlertController(title: "Go Back.", message: "Try Once Again", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.myActivityIndicator.stopAnimating()
self.myActivityIndicator.hidesWhenStopped = true
tableView.reloadData()
}
There are a few things that might cause your delegate methods to not be called:
Your rest client is nil or is being released (e.g., by ARC) prematurely.
You're making the call in a background thread that doesn't have a run loop.
Your delegate method that should be called back has a typo in it. Unfortunately the SDK doesn't warn you if it can't find a delegate method to call; it just completes without telling anyone.
Also, note that the SDK you're using uses API v1, which is deprecated and being retired soon anyway:
https://blogs.dropbox.com/developers/2016/06/api-v1-deprecated/
You should switch to API v2:
https://www.dropbox.com/developers/documentation
I'm following a course online, the app I'm building is basically a cut down version of Instagram as you can see on the left hand side I have a view for signing in, on the right hand side I have a view for signing up.
Pretty straight forward right, now I have created a Seque from the signin page from the button Register which when pressed takes you to the registration view (one on the right), this works as expected however if I'm on the signin page and click sign in and it errors for whatever reason I display the error message but straight after is performs the Seque to the registration screen even though I never pressed register
This is my storyboard:
This is my code behind the Sign In button located on the left view
#IBAction func btnSignIn(sender: AnyObject) {
if txtUsername.text == "" || txtPassword.text == "" {
displayAlert("Error", message: "Username and Password required!")
}
}
I have no other code inside this controller which would cause the Seque to initialise.
If someone can shed some light into how I can stop this Seque from happening on Sign In click and only happen when I press Register I'd appreciate it.
Update
After further investigation this seems to be an issue with my alert box I'm displaying. If I comment out the alert box and press signin and let it error yet not display anything then click register which takes me to the view on the right, click sign in and get taken back to view on the left and then press Sign In display the alert box and when it closes it seems like it thinks the view controller that's being displayed in the one previous to the current one on the page, which is odd. This is my alert function:
func displayAlert(title: String, message: String) { // Display alert message to user. Passing in title and message which will be displayed.
if #available(iOS 8.0, *) {
let a = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
a.addAction((UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
})))
self.presentViewController(a, animated: true, completion: nil)
} else {
// Fallback on earlier versions
}
}
You don't need to dismiss the alert view controller in the action. When the user selects an action, the alert controller is automatically dismissed.
Since you are calling dismissViewControllerAnimated you are going back to the previous view controller.
Right click on Sign-in button and check Connections Inspector, may be you have copy-pasted these two buttons so the action of both sign-in and register button would be same.
I am getting a very strange error. I think the compiler is trying to tell me that it can't segue to another view controller until it is done executing all the code in my current view controller but I am not sure.
I'm literally getting input by using an alert box (i.e. calling a function called generateTextField).
Then when I am done I'm saying "Hey I want you to go to another view controller" - but the the compiler instead tells me "Hey I don't think so".
Here is my error:
Warning: Attempt to present HairStyle1ViewController: 0x7...> on browseBarbersViewController: 0x7...> which is already presenting
Warning: Attempt to present HairStyle1ViewController: 0x7..> on browseBarbersViewController: 0x7...> which is already presenting
#IBAction func AddNewStyleButtonClicked(sender: AnyObject)
{
// Get the "hairstyle name" from the user
generateTextField();
// OK We are done with that function, now transition to the
// next screen
performSegueWithIdentifier("HairStyle1", sender: self);
}
// Generate a text field for user input (i.e. call the alert function)
func generateTextField()
{
//1. Create the alert controller.
var tempStyle = "";
var alert = UIAlertController(title: "Add a New Style", message: "Enter the name of the new hairstyle below", preferredStyle: .Alert);
//2. Add the text field. You can configure it however you need.
alert.addTextFieldWithConfigurationHandler({ (textField) -> Void in
textField.placeholder = "Your New Hairstyle Goes Here..";
})
//3. Grab the value from the text field, and print it when the user clicks OK.
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
let textField = alert.textFields![0] as UITextField
tempStyle = textField.text!;
print("New Style Added is: " + tempStyle);
HairStyle = tempStyle;
}))
// 4. Present the alert.
self.presentViewController(alert, animated: true, completion: nil)
}
It's also weird that when I take out the generateTextField() function it performs the segue perfectly. I'm very confused.
Wow, I figured it out. I had to instead, segue in the body of the alert function.
I fixed this by adding
self.performSegueWithIdentifier("HairStyle1", sender: self);
after the
HairStyle = tempStyle; line
So the first thing my app does is get a list of movies from an API. I'm trying to handle if there's a network issue. Currently, in my viewDidLoad method, I call "updateApiInfo", which contains the following code:
if self.movies == nil {
print("stuff went wrong")
let alert = UIAlertController(title: "Network Error", message: "There was a nework error.\nYou must be connected to the internet to use Flicks.", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Exit", style: UIAlertActionStyle.Default, handler: {(UIAlertAction) in
UIControl().sendAction(Selector("suspend"), to: UIApplication.sharedApplication(), forEvent: nil)
}))
self.presentViewController(alert, animated: true, completion: nil)
}
When viewDidLoad calls updateApiInfo, I get this message:
Warning: Attempt to present <UIAlertController: 0x7fad10e3ad80> on <Flicks.MoviesViewController: 0x7fad10e35cc0> whose view is not in the window hierarchy!
When I call updateApiInfo just from the user refreshing, the error pops up as expected.
I'm assuming that viewDidLoad only gets called before the view gets displayed to the user, which I guess is causing this error. Is there a method I can stick this code in for after the view is displayed to the user, so the problem can presumably get fixed?
You need to use viewDidAppear: to make sure the view is already in the window hierarchy.
There's a pretty good explanation of the order in which the methods are called here:
What is the process of a UIViewController birth (which method follows which)?
I am creating an app, and to access the main screen of the app the user has to input there fingerprint. I have it setup so that when the fingerprint is correct it programmatically performs a segue to a navigation controller which is connected to the main view controller. Here is my code:
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.DeviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Authenticate with Touch ID"
context.evaluatePolicy(.DeviceOwnerAuthenticationWithBiometrics, localizedReason: reason, reply:
{(succes: Bool, error: NSError!) in
if succes {
self.showOrHide(true)
ProgressHUD.showSuccess("Success")
self.performSegueWithIdentifier("passwordCorrectSegue", sender: nil)
} else {
}
})
} else {
self.touchIDLabel.hidden = true
self.touchIDImage.hidden = true
}
The problem is when I perform the segue and it goes to the navigation controller which shows the view controller, the UIBarButtonItem's do not show on the top left and top right of the screen. You can still click on the top left and top right of the screen and the actions for those buttons would run. The problem is that the UIBarButtonItem's are just not showing. Another thing I have tried is that you also have the option to enter in a password, and when the password is correct it goes to the next view controller... and it works perfectly. Does anyone know how to fix this?
The UIBarButtonItems just don't show when I use the method
self.performSegueWithIdentifier("passwordCorrectSegue", sender: nil)
when trying to perform that method using the fingerprint method.
I had the exact same issue: I have 2 VC, each being able to segue to a third one ; if I segue from the first, the right bar button item is not visible (but still works), but if I segue from the second one, the right bar button item is visible.
I guess it's a bug in iOS9.
The workaround I used was to force the initialization of the right bar button item in the destination view controller "viewDidLoad":
override func viewDidLoad() {
super.viewDidLoad()
// Force right bar button item when using performSeguewithIdentifier (bug in iOS9?)
navigationItem.rightBarButtonItem = UIBarButtonItem(
image: UIImage(assetIdentifier: .Profile),
style: UIBarButtonItemStyle.Plain,
target: self,
action: Selector("displayUser"))
}
That fixed the issue for me (at least until Apple fixes this bug).