Swift performSegueWithIdentifier not working

I am trying to switch view controllers after a user successfully logs into their account, but it does not work correctly. I cannot use segue directly, because if I click on the login button, it will go to this view controller, regardless of whether the information is correct or not. I tried everything that I know without success. This is the code I'm trying to do.

@IBAction func loginTapped(sender: AnyObject) { let username = usernameField.text let password = passwordField.text if username.isEmpty || password.isEmpty { var emptyFieldsError:UIAlertView = UIAlertView(title: "Please try again", message: "Please fill in all the fields we can get you logged in to your account.", delegate: self, cancelButtonTitle: "Try again") emptyFieldsError.show() } PFUser.logInWithUsernameInBackground(username, password:password) { (user: PFUser?, error: NSError?) -> Void in if user != nil { self.performSegueWithIdentifier("Klikur", sender: self) } else { if let errorString = error!.userInfo?["error"] as? String { self.errorMessage = errorString } self.alertView("Please try again", message: "The username password combiation you have given us does not match our records, please try again.", buttonName: "Try again") } } } 

I have the storyboard identifier set to "Test" and it does not switch the view controller when the correct information is entered. Can someone help me solve my problem?

Here is the code for LoginViewController Here is the attribute panel for KlikurTableViewController

+27
source share
8 answers

[Assuming your code is not crashing but just won't work]

At least one problem:

 self.performSegueWithIdentifier("Test", sender: self) 

it should be:

 dispatch_async(dispatch_get_main_queue()) { [unowned self] in self.performSegueWithIdentifier("Test", sender: self) } 

Remember that all user interface operations must be performed in the main thread queue. You can prove that you are in the wrong thread by checking:

 NSThread.isMainThread() // is going to be false in the PF completion handler 

ADDITION

If any chance of self can become null, for example, dismissal or another release because it is not needed, you should fix yourself weakly as [weak self] not unowned and use safe unpacking: if let s = self { s.doStuff() } or optional chain: self?.doStuff(...)

APPENDIX 2

This seems to be a popular answer, so it's important to mention this newer alternative here:

 NSOperationQueue.mainQueue().addOperationWithBlock { [weak self] in self?.performSegueWithIdentifier("Test", sender: self) } 

Please note: https://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-swift :

NSOperation vs. Grand Central Dispatch (GCD)

GCD [dispatch_ * calls] is a lightweight way of representing the units of work that will be executed simultaneously.

NSOperation adds a bit of extra overhead compared to GCD, but you can add dependency between different operations and reuse, cancel or pause them.

APPENDIX 3

Apple hides a single-threaded rule:

Note

For the most part, use UIKit classes only from the main application stream. This is especially true for classes derived from UIResponder, or that involve controlling the user interface of applications in any way.

Link:

https://developer.apple.com/documentation/uikit

+53
source

I have the same problem with login problem. probably we are doing the same tutorial. After naming your segue id, you need to replace:

 performSegueWithIdentifier("Klikur", sender: self) 

with:

 dispatch_async(dispatch_get_main_queue()){ self.performSegueWithIdentifier("Klikur", sender: self) } 

The seque type must be set to "show (e.g. Push)" in the segue storyboard. Hope this works.

+17
source

The segue identifier you pass to performSegueWithIdentifier(_:sender:) must exactly match the identifier you specified in the storyboard. I assume that you have a segue between the login controller and the result view controller, which should be; if not, ctrl + drag from the first to the second view controller, then select the segue icon in the storyboard and set its Klikur identifier. Do not navigate at the touch of a button, as one commentator said, because this defeats the main purpose of the sessions, which should give a visual indication of the flow of the application in the storyboard.

EDIT: here is the code for the login controller:

 import UIKit class ViewController: UIViewController { @IBOutlet weak var usernameField: UITextField! @IBOutlet weak var passwordField: UITextField! @IBAction func attemptLogin(sender: AnyObject) { if !usernameField!.text!.isEmpty && !passwordField!.text!.isEmpty { performSegueWithIdentifier("Klikur", sender: self) } } override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if "Klikur" == segue.identifier { // Nothing really to do here, since it won't be fired unless // shouldPerformSegueWithIdentifier() says it ok. In a real app, // this is where you'd pass data to the success view controller. } } } 

And a screenshot of the segue properties I'm talking about: enter image description here

+7
source

swift 3.x

 DispatchQueue.main.async(){ self.performSegue(withIdentifier: "Klikur", sender: self) } 
+5
source
 DispatchQueue.main.async() { self.performSegue(withIdentifier: "GoToHomeFromSplash", sender: self)` } 
+2
source

Make sure you execute segue on the visible controller.

This is an edge case, but my runtime failure failed when I tried to run it on a view controller owned by my UIPageViewController, which is not currently displayed. It also failed if I tried to execute segue on all view controllers belonging to my UIPageViewController, including the view controller currently being displayed. The fix was to keep track of which view manager was currently visible in my UIPageViewController and only run a session on that view controller.

+1
source

Make sure you put self.performSegue(withIdentifier: ..., ...) : self.performSegue(withIdentifier: ..., ...)

in viewDidAppear or later. It will not work in viewWillAppear or viewDidLoad.

+1
source

Login example. When you have success in your login after clicking the (Action) button, you can use:

 self.performSegue(withIdentifier: "loginSucess", sender: nil) 

But if you run the application and you have credentials from your keychain, you need to use this as part of the panel:

 DispatchQueue.main.async(){ self.performSegue(withIdentifier: "sessionSuccess", sender: nil) } 
0
source

Source: https://habr.com/ru/post/1245441/


All Articles