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

}

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

Вот код для LoginViewController Вот панель атрибутов для KlikurTableViewController

Ответ 1

[Предполагая, что ваш код не сбой, а просто не сработает]

По крайней мере одна проблема:

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] not 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 против Grand Central Dispatch (GCD)

GCD [dispatch_ * calls] - это облегченный способ представления единиц работы, которые будут выполняться одновременно.

NSOperation добавляет немного дополнительных накладных расходов по сравнению с GCD, но вы можете добавить зависимость между различными операциями и повторно использовать, отменить или приостановить их.

ДОБАВЛЕНИЕ 3

Apple скрывает однопоточное правило:

Примечание

По большей части используйте классы UIKit только из основного потока приложений. Это особенно справедливо для классов, полученных из UIResponder, или того, что вовлекайте управление пользовательским интерфейсом приложений любым способом.

Ссылка:

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

Ответ 2

У меня такая же проблема с проблемой входа. вероятно, мы делаем один и тот же учебник. После именования вашего идентификатора segue вам необходимо заменить:

performSegueWithIdentifier("Klikur", sender: self)

с:

dispatch_async(dispatch_get_main_queue()){

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

}

тип seque должен быть установлен как "show (например, Push)" в segue раскадровки. Надеюсь, что это сработает.

Ответ 3

Идентификатор segue, который вы передаете в performSegueWithIdentifier(_:sender:), должен точно соответствовать идентификатору, указанному вами в раскадровке. Я предполагаю, что у вас есть segue между контроллером входа в систему и контроллером представления результатов, что и должно быть; если нет, ctrl + перетащить с первого на второй контроллер представления, затем выберите значок segue в раскадровке и установите его идентификатор 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 ok. In a real app,
            // this is where you'd pass data to the success view controller.
        }
    }

}

И скриншот свойств segue, о которых я говорю: введите описание изображения здесь

Ответ 4

swift 3.x

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

Ответ 5

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

Ответ 6

Убедитесь, что вы выполняете выполнение segue на видимом контроллере.

Это краевой случай, но мой сбой выполнения не удался, когда я попытался запустить его на контроллере представления, принадлежащем моему UIPageViewController, который в настоящее время не отображается. Он также потерпел неудачу, если я попытался выполнить segue на всех контроллерах представлений, принадлежащих моему UIPageViewController, включая отображаемый в настоящее время контроллер вида. Исправление заключалось в том, чтобы отслеживать, какой диспетчер представлений был в настоящее время видимым в моем UIPageViewController, и выполнять только сеанс на этом контроллере представления.

Ответ 7

Удостоверьтесь, что вы помещаете свой: self.performSegue(withIdentifier: ..., ...)

в viewDidAppear или позже. Он не будет работать в viewWillAppear или viewDidLoad.

Ответ 8

Пример в логине. Когда у вас есть успех в вашем логине после нажатия кнопки (Действие), вы можете использовать:

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

Но если вы запускаете приложение, и у вас есть учетные данные из вашей связки ключей, вам нужно использовать это как часть панели:

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