How do I set up an UIScreenEdgePanGestureRecognizer using Interface Builder?
Solution 1
I set up a project to test your question and found the same issue you did. Here are the scenarios I set up to test:
-
I did exactly as you did, using Interface Builder, to build the screen edge gesture. The only difference in my code is that I put a line of code in the selector so the debugger would have something to stop on. The debugger failed to halt exactly as you found.
-(void)handlePan:(id)sender { NSString *test = @""; }
I then created an additional gesture using the pinch gesture on the same view using Interface Builder and I was able to get the debugger to halt within that selector. So Interface Builder seems to be able to build other gestures correctly.
- I then created the screen edge gesture manually using the following code and it worked as expected.
In the ViewController.h file I included the UIGestureRecognizerDelegate.
@interface ViewController : UIViewController <UIGestureRecognizerDelegate>
@end
In the ViewController.m file I implemented the gesture manually.
#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
I ended up with the same conclusion you did - there seems to be something wrong with the Interface Builder's implementation of the UIScreenEdgePanGestureRecognizer.
Solution 2
I have tried it in Xcode 7.0 Beta 4 (7A165t) and it's still a bug. Adding the Screen Edge Pan Gesture Recognizer via Interface Builder doesn't call the referenced IBAction, however adding it programmatically like this works fine:
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!")
}
}
}
Hint: Don't forget to add the UIGestureRecognizerDelegate protocol to your class. Otherwise you'll get an error at edgeGestureRecognizer.delegate = self
Solution 3
It can be considered as a bug, but actually, here is something useful:
"After creating a screen edge pan gesture recognizer, assign an appropriate value to the edges property before attaching the gesture recognizer to your view."
This requirement only apply to UIScreenEdgePanGestureRecognizer, so I think that's why Xcode make it wrong, it must be implemented as the normal sequence, alloc->init->attach->set value. It will work to all other GestureRecongnizer but not UIScreenEdgePanGestureRecognizer.
Solution 4
Xcode isn’t always a good neighbor. Sorry.
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)")
}
Solution 5
To make sure that multiple gesture recognizers can work together you have to implement the method shouldRecognizeSimultaneouslyWithGestureRecognizer
and return true:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
Sorry for the Swift code but you should get the idea.
This method must be implemented even if you are using a single gesture recognizer because the view can have its own (system) recognizers, such as MKMapView
.
Comments
-
j b almost 2 years
I can't get
UIScreenEdgePanGestureRecognizer
to work when I create when I add it to my view controller using Interface Builder, so I'm asking here to establish whether I'm doing something wrong or if there is a bug in Xcode.Here are the steps to reproduce:
- Create a new Xcode project using the "Single View Application" template for iOS.
- Add a
UIView
to the main view controller by dragging one from the Object Library in Interface Builder - Add a
UIScreenEdgePanGestureRecognizer
to the view by dragging one from the Object Library in Interface Builder - Ensure that the gesture recogniser is enabled and that an edge is selected:
- Open the assistant editor for the
ViewController
class and ctrl-drag from theUIScreenEdgePanGestureRecognizer
to theViewController
's implementation block to create a newIBAction
` Add a breakpoint in the action's method body to test if the edge pan gesture is being recognized
The resulting code is as follows:
If I run the application on my device (iPhone 6 running iOS 8.02) the breakpoint does not get hit when I do an edge swipe.
Is there something I'm missing?
UPDATE: this was filed as a bug with Apple (rdar://18582306) on 08-Oct-2014 and still isn't resolved in Xcode 6.4 (6E35b)