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")
        }
    }

}

У меня есть идентификатор раскадровки, установленный на "тест", и он не переключает контроллер вида, когда правильный вводится информация. Может кто-нибудь помочь мне решить мою проблему?

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

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)
}

ссылки:

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


у меня такая же проблема с проблемой входа. наверное, мы делаем то же самое. После именования идентификатора 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.
        }
    }

}

и скриншот свойств segue, о которых я говорю: enter image description here


swift 3.x

DispatchQueue.main.async(){
    self.performSegue(withIdentifier: "Klikur", sender: self)
}

убедитесь, что вы кладете: 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)
}