web-dev-qa-db-fra.com

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

J'ai une vue de table simple où je gère l'action de sélection sur la vue de table. Cette action fait suite à une séquence.

Si la séquence est une séquence Push, la vue suivante s'affiche immédiatement. Si la séquence est une séquence modal, la vue suivante est soit:

  • prend environ 6 secondes pour afficher
  • s'affiche immédiatement si je tape à nouveau (deuxième pression)

J'ai essayé de chercher quelques idées, mais aucune ne semble applicable à ma situation. En particulier:

  • J'effectue la séquence sur le thread principal de l'interface utilisateur
  • Ma vue est très simple (donc il n'y a pas de problème dans viewDidLoad). De plus, le fait qu'il s'affiche presque instantanément lorsque la séquence est Push indique qu'il n'y a aucun problème à charger la vue cible
  • J'ai essayé de passer nil au sender; même effet.

Quelqu'un a-t-il des idées à ce sujet?

44
tng

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

Vous pouvez le changer pour toute autre option (dans le storyboard Attribute inspector, définissez le champ Selection) et cela fonctionnera très bien (ça marche pour moi ...). Le contre est qu'il gâche l'interface utilisateur de la cellule.

Vous pouvez appeler le segue en DispatchQueue.main.async{} bloquer à la fonction de délégué didSelect de UITableViewDelegate comme les gens le mentionnent auparavant.

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 rendra la cellule `` en surbrillance '' au robinet, mais elle reviendra immédiatement à son interface utilisateur habituelle et cela me conviendra ...

5
Yedidya Reiss

Il semble y avoir diverses situations où effectuer une transition ne fonctionnera pas correctement. Par exemple, si vous appelez performSegue à partir du gestionnaire d'actions d'un enchaînement de déroulement, vous rencontrerez divers problèmes, même si vous êtes sur le thread principal. Sur mon projet actuel, j'appelle performSegue à partir de la méthode didSelectRowAt d'une vue de table. C'est l'une des séquences les plus élémentaires et bien sûr je suis sur le fil principal, mais je voyais les symptômes exacts décrits par l'OP.

Je ne sais pas pourquoi cela se produit dans certains cas et pas dans d'autres, mais j'ai constaté que le report de l'appel de performSegue à l'aide de async résout tous les problèmes potentiels. Cela ressemblait à un hack et me rendait nerveux, mais à ce stade, j'ai plusieurs projets matures utilisant cette approche et cela semble maintenant être la "bonne" façon de faire une séquence manuelle.

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

DispatchQueue.main.async {
    self.performSegue(withIdentifier: "theIdentifier", sender: theSender)
}
3
phatmann

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
instAustralia

J'espère que cela vous aidera à créer une transition modale programmatique comme celle-ci 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
Dasoga

Pour les développeurs organisant leur code via le sous-classement, je suis arrivé à 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)
    }
  }
}

Ensuite, appelez-le simplement depuis votre implémentation:

myViewController.performSegueOnMainThread(with: "ShowDetailsSegue", sender: self)
1
Hans Knöchel

Pour moi, c'était le fait que j'avais trop de vues colorées "claires" dans ma vue suivante, donc lorsque la séquence était animée, il semblait que cela retardait à cause de cela. J'ai parcouru la hiérarchie de l'interface utilisateur du contrôleur de vue à la recherche de couleurs claires et en les remplaçant par du noir ou du blanc solide, et en m'assurant que l'alpha est 1 (s'il ne devait pas en être autrement). Mon retard a maintenant disparu et ma présentation modale est fluide.

0
Joshua Hart