Swift performSegueWithIdentifier не работает
Я пытаюсь переключить контроллеры представления после успешного входа пользователя в свою учетную запись, но он работает неправильно. Я не могу использовать segue напрямую, потому что если нажать кнопку входа в систему, она перейдет к этому контроллеру представления независимо от того, правильная информация или нет. Я испробовал все, что знал, но безуспешно. Это код, который я пытаюсь.
@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")
}
}
}
У меня есть идентификатор раскадровки, установленный на "тест", и он не переключает контроллер вида, когда правильный вводится информация. Может кто-нибудь помочь мне решить мою проблему?
8 ответов
[предполагая, что ваш код не сбой, а просто не в состоянии сегментировать]
по крайней мере одна проблема:
self.performSegueWithIdentifier("Test", sender: self)
должно быть:
dispatch_async(dispatch_get_main_queue()) {
[unowned self] in
self.performSegueWithIdentifier("Test", sender: self)
}
помните, что все операции пользовательского интерфейса должны выполняться в очереди основного потока. Вы можете доказать себе, что находитесь в неправильном потоке, проверив:
NSThread.isMainThread() // is going to be false in the PF completion handler
дополнительное соглашение
если есть хоть какой-то шанс self
может стать нулевым, например, увольнение или в противном случае освобождается, потому что это не нужно, вы должны захватить себя слабо, как [weak self]
не unowned
, и используйте безопасный разворачивать:if let s = self { s.doStuff() }
или необязательно цепочки: self?.doStuff(...)
добавление 2
это, кажется, популярный ответ, поэтому важно упомянуть эту новую альтернативу здесь:
NSOperationQueue.mainQueue().addOperationWithBlock {
[weak self] in
self?.performSegueWithIdentifier("Test", sender: self)
}
Примечание, от https://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-swift:
NSOperation vs. Grand Central Dispatch (GCD)
GCD [dispatch_* calls] - это легкий способ представления единиц работы, которые будут выполняться одновременно.
NSOperation добавляет немного дополнительных накладных расходов по сравнению с GCD, но вы можете добавить зависимость между различными операциями и повторно использовать, отменить или приостановить их.
добавление 3
Apple скрывает однопоточное правило здесь:
Примечание
по большей части используйте классы UIKit только из основного потока вашего приложения. Это особенно верно для классов, производных от UIResponder или что каким-либо образом манипулируйте пользовательским интерфейсом вашего приложения.
SWIFT 4
DispatchQueue.main.async(){
self.performSegue(withIdentifier: "Test", sender: self)
}
ссылки:
у меня такая же проблема с проблемой входа. наверное, мы делаем то же самое. После именования идентификатора segue необходимо заменить:
performSegueWithIdentifier("Klikur", sender: self)
С:
dispatch_async(dispatch_get_main_queue()){
self.performSegueWithIdentifier("Klikur", sender: self)
}
тип seque должен быть установлен как " show (например, Push)" в раскадровке. Надеюсь, это сработает.
идентификатор segue, который вы передаете performSegueWithIdentifier(_:sender:)
должны ровно соответствует идентификатору, который вы дали segue в раскадровке. Я предполагаю, что у вас есть сегмент между контроллером вида входа в систему и контроллером вида успеха, как и должно быть; если нет, ctrl + перетащите с первого на второй контроллер вида, затем выберите значок сегмента в раскадровке и установите его ID в Klikur
. не выполните навигацию по нажатию кнопки, как сказал один комментатор, потому что теряется основной целью переходами, который давать визуальный индикация потока приложений в раскадровке.
EDIT: вот код для контроллера вида входа в систему:
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's ok. In a real app,
// this is where you'd pass data to the success view controller.
}
}
}
убедитесь, что вы кладете:
self.performSegue(withIdentifier: ..., ...)
в viewDidAppear или более поздней версии. Он не будет работать в viewWillAppear или viewDidLoad.
DispatchQueue.main.async() {
self.performSegue(withIdentifier: "GoToHomeFromSplash", sender: self)`
}
убедитесь, что вы используете perform segue на контроллере видимого вида.
Это крайний случай, но мой выполнить segue не удалось, когда я попытался запустить его на контроллере представления, принадлежащем моему UIPageViewController, который в настоящее время не отображается. Это также не удалось, если я попытался сделать сегмент на всех контроллерах представления, принадлежащих моему UIPageViewController, включая контроллер представления, видимый в настоящее время. Исправление было отследить, какой контроллер смотреть сейчас отображается в моем UIPageViewController и выполняет только сегмент на этом контроллере представления.
пример В логине. При успешном входе в систему после нажатия кнопки (действия) вы можете использовать:
self.performSegue(withIdentifier: "loginSucess", sender: nil)
но если вы запускаете приложение, и вы получили учетные данные из своего брелка, вам нужно использовать это как часть theard:
DispatchQueue.main.async(){
self.performSegue(withIdentifier: "sessionSuccess", sender: nil)
}