Reputation: 3544
I'm trying to make a Segue programmatically using "performSegueWithIdentifier" but for some reason it's not working. I'm going to post my code because it's really simple but it's showing a weird error.
Here you are my code:
import UIKit
class LoginViewController: UIViewController {
@IBOutlet weak var login: UIButton!
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.
}
@IBAction func loginButtonPressed(sender: UIButton) {
if (((user.text) != "") && ((password.text) != ""))
{
let request = NSMutableURLRequest(URL: NSURL(string: "http://website.com/login.php")!)
request.HTTPMethod = "POST"
let postString = "user="+user.text!+"&password="+password.text!
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil
{
print(error)
return
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
if (responseString=="Correct")
{
self.performSegueWithIdentifier("loginSegue", sender: sender)
}
else
{
}
}
task.resume()
}
else
{
}
}
I have already created a Segue from my LoginViewController
to a NavigationController
with the ID "loginSegue", but it still not working.
What's wrong in my code?
That's the error from Xcode:
2015-11-23 21:09:43.224 App[5511:3896125] *** Assertion failure in - [UIKeyboardTaskQueue waitUntilAllTasksAreFinished], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3512.29.5/Keyboard/UIKeyboardTaskQueue.m:378
2015-11-23 21:09:43.226 App[5511:3896125] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIKeyboardTaskQueue waitUntilAllTasksAreFinished] may only be called from the main thread.'
*** First throw call stack:
(0x2232985b 0x33c9edff 0x22329731 0x230baddb 0x2648a5fd 0x2648aeaf 0x2648483b 0x26aa2321 0x265f2b23 0x267c44e7 0x267c5e55 0x267c81e5 0x267c8451 0x26556367 0x267cb6e7 0x267cb735 0x267dfb99 0x267cb65b 0x26a6e6b9 0x26b45919 0x26b45747 0x267bd87d 0x72fd0 0x71b0c 0x6e560 0x21b505b5 0x21b5fcd7 0x230e856d 0x23049fdf 0x2303c3cf 0x230ea82d 0x11e461b 0x11dcf53 0x11e5b0f 0x11e5961 0x34558e0d 0x345589fc)
libc++abi.dylib: terminating with uncaught exception of type NSException
Upvotes: 1
Views: 353
Reputation: 131418
NSURLSession's completion blocks are called on the sessions's delegate queue, which is run on a background thread unless you specify otherwise.
You should not call any UI code (pretty much the entire UIKit) from a background thread. Sometimes it works, sometimes it doesn't do anything, and sometimes it crashes. Don't do it.
Thus you can't do ANY UI code in those completion blocks unless you send that code to the main thread, as Dan says in his answer.
The changed code might look like this:
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil
{
print(error)
return
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
if (responseString=="Correct")
{
//Use dispatch_async to do the performSegueWithIdentifier
//on the main thread.
dispatch_async(dispatch_get_main_queue())
{
self.performSegueWithIdentifier("loginSegue", sender: sender)
}
}
else
{
}
}
Upvotes: 3
Reputation: 1021
The most "simple" fix for this would probably be to just wrap the call to self.performSegueWithIdentifier("loginSegue", sender: sender)
in a dispatch_async
on the main thread, but, it is likely that there are other issues with the destination controller's code that we are not able to see here.
The issue is most likely that NSURLSession
's delegateQueue
is not the main queue, and, something that [UIKeyboardTaskQueue waitUntilAllTasksAreFinished]
is being called somewhere in that thread but it can only be called on the main thread.
Upvotes: 0