web-dev-qa-db-fra.com

Comment configurer un UIScreenEdgePanGestureRecognizer à l'aide d'Interface Builder?

Je ne peux pas faire fonctionner UIScreenEdgePanGestureRecognizer lorsque je crée quand je l'ajoute à mon contrôleur de vue à l'aide d'Interface Builder, donc je demande ici de déterminer si je fais quelque chose de mal ou s'il y a un bogue dans Xcode.

Voici les étapes pour reproduire:

  • Créez un nouveau projet Xcode à l'aide du modèle "Application vue unique" pour iOS.
  • Ajoutez un UIView au contrôleur de vue principal en en faisant glisser un depuis la bibliothèque d'objets dans Interface Builder
  • Ajoutez un UIScreenEdgePanGestureRecognizer à la vue en faisant glisser un depuis la bibliothèque d'objets dans Interface Builder
  • Assurez-vous que la reconnaissance des gestes est activée et qu'un Edge est sélectionné:

enter image description here

  • Ouvrez l'éditeur d'assistant pour la classe ViewController et faites glisser la touche Ctrl du UIScreenEdgePanGestureRecognizer vers le bloc d'implémentation de ViewController pour créer un nouveau IBAction `Ajoutez un point d'arrêt dans le corps de la méthode de l'action pour tester si le geste de panoramique Edge est reconnu

Le code résultant est le suivant:

Code example

Si j'exécute l'application sur mon appareil (iPhone 6 exécutant iOS 8.02), le point d'arrêt n'est pas atteint lorsque je fais un balayage Edge.

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

MISE À JOUR: cela a été classé comme bogue avec Apple (rdar: // 18582306) le 08-Oct-2014 et n'est toujours pas résolu dans Xcode 6.4 (6E35b) =

20
j b

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

  • J'ai fait exactement comme vous, en utilisant Interface Builder, pour construire le geste Edge d'écran. La seule différence dans mon code est que j'ai mis 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
    {
        NSString *test = @"";
    }
    
  • J'ai ensuite créé un geste supplémentaire en utilisant le geste de pincement sur la même vue à l'aide d'Interface Builder et j'ai pu arrêter le débogueur dans ce sélecteur. Ainsi, Interface Builder semble être capable de créer correctement d'autres gestes.

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

Dans le fichier ViewController.h, j'ai inclus le UIGestureRecognizerDelegate.

@interface ViewController : UIViewController <UIGestureRecognizerDelegate>
@end

Dans le fichier 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
{
    NSString *test = @"";
}

@end

Je me suis retrouvé avec la même conclusion que vous - il semble y avoir un problème avec l'implémentation par Interface Builder de UIScreenEdgePanGestureRecognizer.

24
sunergeos

Je l'ai essayé dans Xcode 7.0 Beta 4 (7A165t) et c'est toujours un bug. L'ajout de Screen Edge Pan Gesture Recognizer via Interface Builder n'appelle pas l'IBAction référencé, mais l'ajouter par programme comme ceci fonctionne très 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!")
        }
    }
}

Indice: N'oubliez pas d'ajouter le protocole UIGestureRecognizerDelegate à votre classe. Sinon, vous obtiendrez une erreur à edgeGestureRecognizer.delegate = self

8
Peter

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

"Après avoir créé un écran de reconnaissance des gestes de panoramique des bords, attribuez une valeur appropriée à la propriété des bords avant d'attacher la 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 pourquoi Xcode le fait mal, il doit être implémenté comme la séquence normale, alloc-> init-> attach-> set value. Cela fonctionnera pour tous les autres GestureRecongnizer mais pas pour UIScreenEdgePanGestureRecognizer.

6
Thomas LIU

Xcode n'est pas toujours un bon voisin. Désolé.

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

Il semble qu'il y ait un bogue dans le générateur d'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 existe des cases à cocher Edge dans IB, elles semblent être ignorées.

Je l'ai résolu de cette façon: Ctrl-faites glisser de la reconnaissance des gestes vers la classe viewController pour créer un IBOutlet:

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

puis, dans viewDidLoad:

leftEdgeGestureRecognizer.edges = .Left

et enfin, faites un ctrl-glisser depuis le module de reconnaissance pour créer une IBAction

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

Pour vous assurer que plusieurs reconnaisseurs de mouvements peuvent fonctionner ensemble, vous devez implémenter la méthode shouldRecognizeSimultaneouslyWithGestureRecognizer et retourner 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 identificateur de mouvements car la vue peut avoir ses propres identificateurs (système), tels que MKMapView.

2
zisoft

Face au même problème depuis longtemps. C'est un bug xcode, il vaut mieux l'ajouter par programme.

1
itsji10dra