performSegueWithIdentifier très lent lorsque la séquence est modale

j'ai une vue de table simple où je gère l'action select sur la vue de table. Cette action suit une séquence.

si la séquence est une push , la vue suivante s'affiche immédiatement. Si la séquence est une modal , la vue suivante peut être:

  • prend 6 secondes ou plus pour afficher
  • montre immédiatement si je tape à nouveau (deuxième tape)

j'ai essayé de regarder autour pour quelques idées, mais aucun ne semble applicable à ma situation. En particulier:

  • je suis exécution de la séquence sur l'INTERFACE principale du fil
  • mon point de vue est très simple (il n'y a donc pas de problème dans viewDidLoad ). De Plus, le fait qu'elle apparaisse presque instantanée lorsque la séquence est push indique qu'il n'y a aucun problème pour charger la vue cible
  • j'ai essayé de passer nil au sender ; même effet.

Quelqu'un a-t-il une idée à ce sujet?

42
demandé sur tng 2015-02-14 00:43:47

7 réponses

faites-moi confiance et essayez ceci. J'ai rencontré ce problème à plusieurs reprises.

Dans Swift 2:

dispatch_async(dispatch_get_main_queue(),{
    self.performSegue(withIdentifier:mysegueIdentifier,sender: self)
})

ou pour Swift 3:

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

Comme discuté de la ici et ici .

85
répondu boidkan 2017-05-23 12:17:52

il me semble (...) que ce problème ne se produit que lorsque la cellule selectionType n'est pas .none .

vous pouvez le changer à n'importe quelle autre option (au storyboard Attribute inspector , mettez le champ Selection ) et il fonctionnera très bien (travailler pour moi...). Le contre, c'est qu'il salisse la cellule de l'INTERFACE utilisateur.

vous pouvez appeler la suite dans DispatchQueue.main.async{} bloc à la didSelect fonction de délégué de UITableViewDelegate comme les gens mentionnent avant.

j'ai utilisé la première solution et ajouté à la cellule elle-même -

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(false, animated: false)
}

cela va faire la cellule 'highlight' au robinet, mais il va revenir à son UI habituelle immédiatement et il va bien pour moi...

4
répondu Yedidya Reiss 2016-10-21 05:41:42

il semble y avoir plusieurs situations où l'exécution d'une séquence ne fonctionnera pas correctement. Par exemple, si vous appelez performSegue du gestionnaire d'action d'une séquence de décompression, vous rencontrerez divers problèmes, même si vous êtes sur le fil principal. Sur mon projet actuel, j'appelle performSegue de la méthode didSelectRowAt d'une vue de table. C'est l'une des étapes les plus basiques et bien sûr je suis sur le fil principal, mais je voyais les symptômes exacts que l'opération décrit.

Je ne sais pas pourquoi cela se produit dans certains cas et pas dans d'autres, mais j'ai constaté que le fait de reporter l'appel performSegue en utilisant async règle tout problème potentiel. Cela ressemblait à un piratage et me rendait nerveux, mais à ce point j'ai plusieurs projets mûrs utilisant cette approche et il semble maintenant comme la "bonne" façon de faire une séquence manuelle.

Voici la version Swift 3 du code (voir les autres posts pour les versions Swift 2 et Obj-C)):

DispatchQueue.main.async {
    self.performSegue(withIdentifier: "theIdentifier", sender: theSender)
}
3
répondu phatmann 2016-10-02 10:35:32

la solution acceptée a fonctionné pour moi. Code mis à jour pour Swift 2.0 ci-dessous:

dispatch_async(dispatch_get_main_queue(),{
     self.performSegueWithIdentifier(mysegueIdentifier, sender:self)
})
2
répondu instAustralia 2015-11-25 02:53:50

l'Espoir d'aider ce yo peut créer par programmation modal de transition de ce genre dans Swift:

       let myStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let modalViewController = myStoryboard.instantiateViewControllerWithIdentifier("myModalViewController") as! myModalViewController
        modalViewController.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
        let navController = UINavigationController(rootViewController: accountManager)
        dispatch_async(dispatch_get_main_queue(),{
            self.presentViewController(navController, animated: true, completion: nil)
        })
1
répondu Dasoga 2016-03-03 17:00:05

pour les développeurs organisant leur code à travers le sous-codage, j'ai trouvé une solution assez simple que je voudrais partager (Swift 4):

import UIKit

class ABCViewController: UIViewController {

  // ... Other useful methods like overriding deinit and didReceiveMemoryWarning

  // Performs a segue on the main thread to ensure it will 
  // transition once a UI-slot is available
  func performSegueOnMainThread(with identifier: String, sender: Any?) {
    DispatchQueue.main.async {
      self.performSegue(with: identifier, sender: sender)
    }
  }
}

alors, appelez-le simplement de votre implémentation:

myViewController.performSegueOnMainThread(with: "ShowDetailsSegue", sender: self)
1
répondu Hans Knöchel 2018-01-01 20:01:57

j'ai essayé de fixer ce plusieurs façons dont y compris le déplacement vers le fil principal ci-dessus. Cela a fonctionné pour moi:

dans storyboard, sélectionnez la vue de la table en question, (sélectionnez-la dans le plan du document pour vous assurer que vous avez la bonne chose. Puis, dans attributes inspector, vous pourrez voir les attributs pour la vue de la table ainsi que le scrollview contenant en dessous (toutes les vues de la table sont basées sur scroll view). Il y a cette stupide petite boîte qui s'appelle "retards" contenu touche". Décochez la case. Il y a aussi un "permet des touches annulables" que j'imagine que vous voulez s'assurer est non vérifié aussi, car je pense que double touches ont été gâcher la mienne.

-1
répondu Bec Martin 2016-03-31 06:22:07