web-dev-qa-db-fra.com

Swift performSegueWithIdentifier ne fonctionne pas

J'essaie de changer de contrôleur de vue après qu'un utilisateur s'est connecté avec succès à son compte, mais cela ne fonctionne pas correctement. Je ne peux pas utiliser une séquence directement, car si le bouton de connexion est cliqué, il ira à ce contrôleur de vue, que les informations soient correctes ou non. J'ai essayé tout ce que je connais sans succès. C'est le code que j'essaye.

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

}

L'ID du storyboard est défini sur "Test" et il ne commute pas le contrôleur de vue lorsque les informations correctes sont entrées. Quelqu'un peut-il m'aider à résoudre mon problème?

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

37
Trenton Tyler

[En supposant que votre code ne plante pas, mais échoue simplement]

Au moins un problème est:

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

devrait être:

dispatch_async(dispatch_get_main_queue()) {
    [unowned self] in
    self.performSegueWithIdentifier("Test", sender: self)
}

N'oubliez pas que toutes les opérations de l'interface utilisateur doivent être effectuées dans la file d'attente du thread principal. Vous pouvez vous prouver que vous êtes sur le mauvais fil en vérifiant:

NSThread.isMainThread() // is going to be false in the PF completion handler

[~ # ~] addenda [~ # ~]

S'il y a une chance que self devienne nul, comme par exemple être congédié ou désalloué autrement parce que ce n'est pas nécessaire, vous devriez vous capturer faiblement en tant que [weak self] Et non unowned, et utiliser un dépliage sécurisé. : if let s = self { s.doStuff() } ou chaînage facultatif: self?.doStuff(...)

ADDENDA 2

Cela semble être une réponse populaire, il est donc important de mentionner cette nouvelle alternative ici:

NSOperationQueue.mainQueue().addOperationWithBlock {
     [weak self] in
     self?.performSegueWithIdentifier("Test", sender: self)
}

Remarque, de https://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-Swift :

NSOperation vs. Grand Central Dispatch (GCD)

GCD [dispatch_ * calls] est un moyen simple de représenter des unités de travail qui vont être exécutées simultanément.

NSOperation ajoute un peu de charge supplémentaire par rapport à GCD, mais vous pouvez ajouter une dépendance entre différentes opérations et les réutiliser, les annuler ou les suspendre.

ADDENDA 3

Apple cache la règle à un seul thread ici:

REMARQUE

Pour la plupart, utilisez les classes UIKit uniquement à partir du fil principal de votre application. Cela est particulièrement vrai pour les classes dérivées de UIResponder ou qui impliquent une manipulation de l’interface utilisateur de votre application.

Swift 4

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

Référence:

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

67
BaseZen

J'ai le même problème avec le problème de connexion. probablement nous faisons le même tutoriel. Après avoir nommé votre identifiant de segment, vous devez remplacer:

performSegueWithIdentifier("Klikur", sender: self)

avec:

dispatch_async(dispatch_get_main_queue()){

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

}

le type de seque doit être défini comme "afficher (par exemple, Push)" dans le scénario du storyboard. J'espère que ça va marcher.

18
Mette

Assurez-vous de mettre votre: self.performSegue(withIdentifier: ..., ...)

in viewDidAppear ou ultérieur. Cela ne fonctionnera pas dans viewWillAppear ou viewDidLoad.

13
GregJaskiewicz

L'identifiant de séquence que vous transmettez à performSegueWithIdentifier(_:sender:) doit correspondre exactement à l'ID que vous avez attribué à la séquence dans le storyboard. Je suppose que vous avez une séparation entre le contrôleur de vue de connexion et le contrôleur de vue de succès, qui est comme il se doit; sinon, ctrl + glisser du premier au deuxième contrôleur de vue, puis sélectionnez l'icône de la séquence dans le storyboard et définissez son ID sur Klikur. N'exécutez pas la navigation sur le clic du bouton, comme l'a dit un intervenant, car cela irait à l'encontre du but principal des séparations, qui est de donner un indication visuelle du flux d'applications dans le storyboard.

EDIT: Voici le code pour un contrôleur de vue de connexion:

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

}

Et une capture d'écran des propriétés de la division dont je parle: enter image description here

8
NRitH

Swift 3.x

DispatchQueue.main.async(){
    self.performSegue(withIdentifier: "Klikur", sender: self)
}
7
Felecia Genet
DispatchQueue.main.async() {
    self.performSegue(withIdentifier: "GoToHomeFromSplash", sender: self)`  
}
4
ibk

Assurez-vous que vous exécutez perform segue sur un contrôleur de vue visible.

Il s'agit d'un cas Edge, mais mon exécution a échoué lorsque j'ai tenté de l'exécuter sur le contrôleur de vue appartenant à mon UIPageViewController qui n'était pas visible actuellement. Cela a également échoué si j'ai tenté de faire la transition sur tous les contrôleurs de vue appartenant à mon UIPageViewController, y compris le contrôleur de vue actuellement visible. Le correctif consistait à déterminer quel contrôleur de vue était actuellement visible dans mon UIPageViewController et à effectuer uniquement la transition sur ce contrôleur de vue.

1
Justin Domnitz

Un exemple dans un login. Lorsque vous avez réussi votre connexion après avoir cliqué sur un bouton (Action), vous pouvez utiliser:

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

Mais si vous lancez l'application et que vous avez les informations d'identification de votre trousseau, vous devez utiliser cette information dans le cadre de la discussion:

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