I am trying to switch view controllers after a user successfully logs in to their account, but it is not working correctly. I cant use a segue directly because if the login
[Assuming that your code is not crashing, but rather just failing to segue]
At least one problem is:
self.performSegueWithIdentifier("Test", sender: self)
should be:
dispatch_async(dispatch_get_main_queue()) {
[unowned self] in
self.performSegueWithIdentifier("Test", sender: self)
}
Remember that all UI operations must be performed on the main thread's queue. You can prove to yourself you're on the wrong thread by checking:
NSThread.isMainThread() // is going to be false in the PF completion handler
ADDENDUM
If there's any chance self
might become nil, such as getting dismissed or otherwise deallocated because it's not needed, you should capture self weakly as [weak self]
not unowned
, and use safe unwrapping: if let s = self { s.doStuff() }
or optional chaining: self?.doStuff(...)
ADDENDUM 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)
}
Note, from https://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-swift:
NSOperation vs. Grand Central Dispatch (GCD)
GCD [dispatch_* calls] is a lightweight way to represent units of work that are going to be executed concurrently.
NSOperation adds a little extra overhead compared to GCD, but you can add dependency among various operations and re-use, cancel or suspend them.
ADDENDUM 3
Apple hides the single-threaded rule here:
NOTE
For the most part, use UIKit classes only from your app’s main thread. This is particularly true for classes derived from UIResponder or that involve manipulating your app’s user interface in any way.
SWIFT 4
DispatchQueue.main.async(){
self.performSegue(withIdentifier: "Test", sender: self)
}
Reference:
https://developer.apple.com/documentation/uikit
An example in a login. When you have success in your login after clicking a button (Action) you can use:
self.performSegue(withIdentifier: "loginSucess", sender: nil)
But if you are launching the app and you got the credentials from your keychain you need to use this as a part of the theard:
DispatchQueue.main.async(){
self.performSegue(withIdentifier: "sessionSuccess", sender: nil)
}
swift 3.x
DispatchQueue.main.async(){
self.performSegue(withIdentifier: "Klikur", sender: self)
}
I've got the same problem with login issue. probably we do the same tutorial. After naming your segue identifier you need to replace:
performSegueWithIdentifier("Klikur", sender: self)
with:
dispatch_async(dispatch_get_main_queue()){
self.performSegueWithIdentifier("Klikur", sender: self)
}
type of seque needs to be set as "show (e.g. Push)" in the storyboard segue. Hope it will work.
Make sure you're putting your:
self.performSegue(withIdentifier: ..., ...)
in viewDidAppear or later. It won't work in viewWillAppear or viewDidLoad.
Check to make sure you are running the perform segue on a visible view controller.
This is an edge case, but my perform segue failed when I attempted to run it on the view controller belonging to my UIPageViewController that was not currently visible. It also failed if I attempted to do the segue on all view controllers belonging to my UIPageViewController, including the view controller currently visible. The fix was to track which view controller was currently visible in my UIPageViewController, and only perform the segue on that view controller.