Comment configurer un UIScreenEdgePanGestureRecognizer en utilisant Interface Builder?

Je n'arrive pas à faire fonctionner UIScreenEdgePanGestureRecognizer quand je crée quand je l'ajoute à mon controller de vue en utilisant Interface Builder, donc je request ici d'établir si je fais quelque chose de mal ou s'il y a un bogue dans Xcode.

Voici les étapes à suivre pour reproduire:

  • Créez un nouveau projet Xcode en utilisant le model "Single View Application" pour iOS.
  • Ajoutez un UIView au controller de vue principal en le faisant glisser depuis la bibliothèque d'objects dans Interface Builder
  • Ajoutez un UIScreenEdgePanGestureRecognizer à la vue en le faisant glisser depuis la bibliothèque d'objects dans Interface Builder
  • Assurez-vous que l'outil de reconnaissance des gestes est activé et qu'un bord est sélectionné:

entrez la description de l'image ici

  • Ouvrez l'éditeur d'assistant pour la class ViewController et faites-le glisser depuis UIScreenEdgePanGestureRecognizer vers le bloc d'implémentation de ViewController pour créer un nouvel IBAction `Ajouter un point d'arrêt dans le corps de la méthode de l'action pour tester si le geste de bord est reconnu

Le code résultant est le suivant:

Exemple de code

Si je lance l'application sur mon appareil (iPhone 6 exécutant iOS 8.02), le point d'arrêt ne sera pas touché lorsque j'effectuerai un glissement de bord.

Y a-t-il quelque chose qui me manque?

UPDATE: ceci a été classé comme un bug avec Apple (rdar: // 18582306) le 08-Oct-2014 et n'est toujours pas résolu dans Xcode 6.4 (6E35b)

J'ai mis en place un projet pour tester votre question et trouvé le même problème que vous avez fait. Voici les scénarios que j'ai mis en place pour tester:

  • J'ai fait exactement ce que vous faisiez, en utilisant Interface Builder, pour build le geste du bord de l'écran. La seule différence dans mon code est que je mets une ligne de code dans le sélecteur pour que le débogueur ait quelque chose à arrêter. Le débogueur n'a pas pu s'arrêter exactement comme vous l'avez trouvé.

     -(void)handlePan:(id)sender { NSSsortingng *test = @""; } 
  • J'ai ensuite créé un geste supplémentaire en utilisant le geste de pincement sur la même vue en utilisant Interface Builder et j'ai réussi à faire en sorte que le débogueur s'arrête dans ce sélecteur. Interface Builder semble donc être capable de build d'autres gestes correctement.

  • J'ai ensuite créé le geste de bord de l'écran manuellement en utilisant le code suivant et cela a fonctionné comme prévu.

Dans le file ViewController.h j'ai inclus le UIGestureRecognizerDelegate.

 @interface ViewController : UIViewController <UIGestureRecognizerDelegate> @end 

Dans le file ViewController.m j'ai implémenté le geste manuellement.

 #import "ViewController.h" @interface ViewController () -(void)handlePan:(id)sender; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UIScreenEdgePanGestureRecognizer *pan = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [pan setEdges:UIRectEdgeLeft]; [pan setDelegate:self]; [self.view addGestureRecognizer:pan]; } -(void)handlePan:(id)sender { NSSsortingng *test = @""; } @end 

Je me suis retrouvé avec la même conclusion que vous – il semble y avoir quelque chose qui ne va pas avec l'implémentation de UIScreenEdgePanGestureRecognizer de l'Interface Builder.

Je l'ai essayé dans Xcode 7.0 Beta 4 (7A165t) et c'est toujours un bug. L'ajout de la reconnaissance de gestes de paneau de bord d'écran via Interface Builder n'appelle pas l'IBAction référencée, mais en l'ajoutant par programmation comme ceci fonctionne bien:

 class ViewController: UIViewController, UIGestureRecognizerDelegate { override func viewDidLoad() { super.viewDidLoad() let edgeGestureRecognizer = UIScreenEdgePanGestureRecognizer(target: self, action: "userSwipedFromEdge:") edgeGestureRecognizer.edges = UIRectEdge.Left edgeGestureRecognizer.delegate = self self.view.addGestureRecognizer(edgeGestureRecognizer) } func userSwipedFromEdge(sender: UIScreenEdgePanGestureRecognizer) { if sender.edges == UIRectEdge.Left { print("It works!") } } } 

Astuce: N'oubliez pas d'append le protocole UIGestureRecognizerDelegate à votre class. Sinon, vous obtiendrez une erreur sur edgeGestureRecognizer.delegate = self

Cela peut être considéré comme un bug, mais en réalité, voici quelque chose d'utile:

"Après avoir créé un outil de reconnaissance des mouvements de panoramique à l'écran, atsortingbuez une valeur appropriée à la propriété edges avant d'attacher le module de reconnaissance des mouvements à votre vue."

https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIScreenEdgePanGestureRecognizer_class/index.html

Cette exigence ne s'applique qu'à UIScreenEdgePanGestureRecognizer, donc je pense que c'est la raison pour laquelle Xcode la rend fausse, elle doit être implémentée comme la séquence normale, alloc-> init-> attach-> set value. Cela fonctionnera pour tous les autres GestureRecongnizer mais pas pour UIScreenEdgePanGestureRecognizer.

Pour vous assurer que plusieurs outils de reconnaissance de gestes peuvent fonctionner set, vous devez implémenter la méthode shouldRecognizeSimultaneouslyWithGestureRecognizer et renvoyer true:

 func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } 

Désolé pour le code Swift, mais vous devriez avoir l'idée.

Cette méthode doit être implémentée même si vous utilisez un seul outil de reconnaissance de mouvements car la vue peut avoir ses propres MKMapView reconnaissance (système), tels que MKMapView .

Xcode n'est pas toujours un bon voisin. Pardon.

 override func viewDidLoad() { super.viewDidLoad() let panGesture = UIScreenEdgePanGestureRecognizer(target: self, action: "panAction:") panGesture.edges = .Left view.addGestureRecognizer(panGesture) } func panAction(sender: UIScreenEdgePanGestureRecognizer) { let translation = sender.translationInView(sender.view!) println("Trans:\(translation)") } 

Il semble qu'il y ait un bug dans le constructor de l'interface de Xcode 6.4 et Swift. En outre, la réponse de Thomas LIU était également correcte: il semble nécessaire de définir la propriété .edge dans le code, plutôt qu'avec Interface Builder.

Même s'il y a des cases à cocher dans IB, elles semblent être ignorées.

Je l'ai résolu de la façon suivante: Ctrl-glisser depuis le reconnaisseur de mouvements vers la class viewController pour créer un IBOutlet:

 class ViewController: UIViewController { @IBOutlet var leftEdgeGestureRecognizer: UIScreenEdgePanGestureRecognizer! 

puis, dans viewDidLoad:

 leftEdgeGestureRecognizer.edges = .Left 

et enfin, Ctrl-glisser à partir du système de reconnaissance pour créer un IBAction

 @IBAction func swipeFromLeft(sender: AnyObject) { print("===> Swipe from left edge.\n") } 

Faire face au même problème depuis longtime. C'est un bug de xcode, il est préférable de l'append par programmation.